Hello all, As you may or may not know, dpkg/apt in K/Ubuntu 11.10 now supports installing packages from foreign architectures. (Otherwise known as MultiArch) The rollout of this feature a little while back had a bit of unfortunate timing with QApt/Muon's feature freeze. As such, QApt/Muon 1.2 do not support MultiArch in Kubuntu 11.10. From reports I have recieved, at the moment multiarch packages installed via other methods (Synaptic, apt-get, dpkg, etc) will show up as a duplicated package in Muon, most likely showing the same name as each other. Aside from that, I do now know how exactly Muon would behave when doing things such as installing upgrades for existing multiarch packages as I do not have a 64-bit installation at the moment. Testing needs to be done, though, since it would be pretty bad if Muon is behaving like aptitude is at the moment.[1] If anybody can step up and detail how Muon handles the case presented in that bug, it would be much appreciated.
Multiarch packages are differentiated from native packages through the addition of the foreign architecture at the end of the package name. Adding support for MultiArch packages within LibQApt could be done with a one-line patch (Return FullName() rather than Name()), but there are other things to consider that may make this solution unwise. To explain this I will need to explain a tiny bit how APT stores/interfaces with package data. I'll try to go easy for those who don't know much about APT, but if you get lost, feel free to skip down towards the last few paragraphs where I'll get to some summary. Only crazy people such as myself work with libapt, after all. ;-) APT memory maps a binary cache file that contains all the metadata of every package (name, version, description, homepage, etc, etc) available. Its API for grabbing the name of a particular package returns a c-string pointer that points to the location of the package name in the cache file. APT's MultiArch support introduced a new function for getting the name of a package along with the architecture identifier, if one is present. This one constructs an std::string from the cache's c-string, and then appends the appropriate architecture string to it. The significance of returning an std::string rather than a c-string is that an std::string makes a copy of the data it is passed, while a c-string is a pointer to a memory location that contains the string data, terminated by a null character. In LibQApt::Package, we provide two functions for getting the name of the Package, Package::name() and Package::latin1Name(). The Package::name() function currently uses the c-string API to get the package name (using latin1Name(), in fact), but it constructs a QString from the c-string, which makes a copy of the data. Package::latin1Name() uses APT's c-string API to return a QLatin1String object. A QLatin1String object is a very small class in Qt that wraps around a c-string pointer and gives it a few operators. (Greater than, less than, etc) In essence, latin1Name() returns nothing more than a pointer to the name data in the package cache, with some convenience functions/operators for QString interoperability. The latin1Name() function is provided so that the name can be retrieved without the data copying/construction overhead of a QString for functions that do not need a QString, such as sorting functions. Since APT's new API for getting the multiarch name of a package constructs and returns a new std::string object, latin1Name() can't really use it reliably. (latin1Name() needs a pointer to a non-temporary copy of the data that can be guaranteed for the lifetime of the Package object) I don't see this as *too* much of an issue, though. Package::latin1Name is mainly used for non-display purposes such as sorting, which, although I'm not certain, probably doesn't really need to know the arch to still sort correctly. Package::name() could be made not to construct a QString from the return of the latin1Name(), but rather from the return value of APT's FullName() function, since QString construction creates a copy of the data anyway. From a technical perspective, that's quite easy and not something I'd worry about. That would represent a somewhat large behavior change, however, which I would worry about. It is why I did not get around this in 1.2 due to its feature freeze. Elaborating on the subject of behavior change, most all Qt classes and function parameters that take QString can be passed the QLatin1Strings returned by latin1Name() and construct QStrings with them. Using latin1Name() in that manner is a bit of an abuse since latin1Name() is geared towards sorting where a QString is not necessary, but there are no guarantees that consumers of LibQApt haven't already used latin1Name() in place of name(). I'm sad to say that even I have sinned in this regard in several places in the Muon Suite, so even if Package::name() was changed to return the MultiArch name, there'd still be several places in Muon that would need to be updated to use Package::name(), or maybe a new Package::fullName() function. The bottom line is that while from a technical perspective multiarch support could be a one-line change, any practical solution would realistically have to go further. Here are some solutions I can see, each with their pro's and con's: 1. Call APT's FullName function in the constructor of each Package object initialized and store it in the PackagePrivate d-pointer class. latin1Name returns a QL1S pointing to this. ====== Pros: - latin1Name() and name() both support multiarch Cons: - Increased memory usage. Caching a copy of the package name for each of our 35,000+ packages would increase the memory usage of any consumer application by around 550 KiB, on average. (Given a 16-byte name, not counting std::string overhead) - Invasive behavior change, will probably^s most certainly break things that use the package name for URL concatenation for changelog and screenshot retrieval, both internally in LibQApt as well as possibly externally. (Among other things) 2.Leave latin1Name() alone, and have Package::name() return the MultiArch Name ====== Pros: - name() returns the multiarch name without the memory overhaead. Cons: - Breaks behavior similar to the last solution. - Consumers using latin1Name for non-sorting uses will have to be changed to use name() 3. Add a new function, Package::fullName(), to return the MultiArch name ====== Pros: - Provides a way for consumers to access the multiarch name - Preserves behavior for existing applications using latin1Name() and name(), so at worst they don't support multiarch Cons: - You still have to implement multiarch in consumer applications, but realistically you would have had to have done that anyways. Summary: Each solution carries its own amount of work, especially since we are past feature freeze. I'm partial to solution #3, personally. In summary, this is what I think we should do: 1. Get a feel for how Muon currently behaves without multiarch support, keeping in mind bug 831768[1] 2. Perform risk analysis between implementing MultiArch support in our LibQApt packages in 11.10 vs not supporting multiarch via graphical tools for Kubuntu 11.10. 3. If it is decided to be the best course of action, implement multiarch support in LibQApt, and update the Muon Suite to use it. 4. Call for testing of multiarch support in the Muon Suite for the remainder of the oneiric cycle, to monitor for possible regressions I would very much like to hear anyone's ideas on both the plan for going forward as well as opinions on the technical solutions for providing multiarch support. I've CC'd both slangasek and mvo so that they can bring their multiarch experience to the discussion. Cheers, Jonathan [1] https://launchpad.net/bugs/831768 -- kubuntu-devel mailing list [email protected] Modify settings or unsubscribe at: https://lists.ubuntu.com/mailman/listinfo/kubuntu-devel
