This session was presented by Stefan Potyra and Steve Langasek on 18th January 2008. {{{ 20:06 sistpoty so a big welcome to everyone for joining the motu school session about library packaging 20:06 sistpoty the session will be split in two parts: 20:07 sistpoty in the first part, we'll dive deeply into the background of shared objects, and how to find out information about these 20:07 sistpoty and in the second part, we'll go through creating a library package by example 20:07 sistpoty so let's start with part 1 20:07 sistpoty First off, shared objects are useful for two different purposes 20:08 sistpoty 1) as a plugin mechanism in conjunction with dlopen 20:08 sistpoty 2) for dynamic libraries, to share code between different projects 20:08 sistpoty as this is about library packaging, we'll be only looking at 2) in this session 20:09 sistpoty First off, (ELF) shared objects are a collection of symbols in different sections together with some meta-information 20:09 sistpoty a symbol denotes a named entity in C (e.g. a function or a variable) 20:09 sistpoty the section will give us some detail about the symbol 20:10 sistpoty btw.: if you have questions, just ask ;) 20:10 sistpoty let's take a look at an example: http://www.potyra.de/library_packaging/example.c 20:10 sistpoty so please everyone download the file 20:11 sistpoty everyone got it? 20:11 warp10 yep! 20:11 mok0 + 20:11 sistpoty great, so let's compile the file: 20:11 sistpoty gcc -c example.c -o example.o 20:12 sistpoty so far, the .o is just a normal object, not a shared object yet... however we can do some stuff with it already 20:12 sistpoty now run 20:12 sistpoty nm example.o 20:12 sistpoty the output are the different symbols defined in example.c 20:14 mok0 what are the letters U, T, t... 20:14 sistpoty for example in line 3, the variable "static_global" is results as symbol "0000000000000000 d static_global" 20:14 sistpoty mok0: will talk about that in a second ;) 20:14 sistpoty when you compare the output of nm, together with the variables of example.c, does anyone see anything odd? 20:15 sistpoty I'll give you a hint: look at the beginning of the function local_function 20:16 sistpoty now, anyone? 20:16 warp10 why local_var isn't listed? 20:16 sistpoty warp10: excellent 20:16 mok0 it's allocated on the call stack 20:17 geser why does static_local_var has a number in the nm output (here: static_local_var.2268)? 20:17 sistpoty excactly... some symbols in C (like local_var) don't need to be stored anywhere, because these are located in the stack 20:18 sistpoty ok, and some variables (like static_local_var) won't result in the same symbols as they are named. This is because the variable is not visible anywhere but in the function, and you can name a variable like this anywhere else 20:18 slangasek geser: that's a very good question whose answer I don't remember :) 20:18 sistpoty and you cannot have two symbols with the same name of course 20:18 mok0 geser: could that number be the offset? 20:19 sistpoty any more questions or shall we go to the funny letters? 20:19 mok0 ^^ 20:19 slangasek mok0: it's not the offset 20:19 warp10 What's the order with which symbols are listed by nm? 20:19 sistpoty warp10: good question: slangasek? 20:20 slangasek plain alphabetical 20:20 siretart slangasek: in order to avoid name clashes between different static local variables with the same name in different functions? 20:20 sistpoty mok0: I guess it's just a counted number gcc will assign, but I may err on this side 20:20 mok0 sistpoty: my number is != gesers 20:20 geser mok0: it could be the line number after including all headers. after changeing the line with the previous one the number is now 2267 20:21 slangasek siretart: probably, yes 20:21 sistpoty mok0: he, ah 20:21 mok0 static_local_var.1781 20:21 slangasek siretart, geser: suffice to say, it goes away once you've linked the object into a shared library, so it ends up not being very relevant 20:22 sistpoty ok, then now let's take a look at the letters. 20:22 sistpoty First off, some are lower case and some are upper case. 20:22 slangasek geser: it isn't the line number; if I run the source through gcc -E, I get line 757 20:22 geser ok 20:22 sistpoty The lower case letters denominate local symbols. Noone except this very object file can see these kind of symbols 20:23 mok0 lower case == local, Upper case == global 20:23 sistpoty whereas the upper case letters mean that the symbol is global, and other object files are global... exactly. 20:23 sistpoty the letter denote the type of the symbol: 20:23 sistpoty t -> text section (may be mapped readonly), executable 20:23 sistpoty d -> initialized data (statics, initialized globals) 20:23 sistpoty (as in variables) 20:24 sistpoty c -> uninitialized data (uninitialized global variables) 20:24 sistpoty r -> read only data (const variables), not necessarily read only though. 20:24 slangasek (btw, if you later don't remember what these letters map to, they're listed in man nm) 20:24 sistpoty and then there's an interesting one: u 20:24 sistpoty this means that the symbol is not defined in the object, but somewhere else 20:25 sistpoty (undefined) 20:25 slangasek to clarify, that means the object *refers* to the symbol but does not define it 20:25 sistpoty so "stderr" is listed there, as it comes somewhere from the c library, as well as fprintf 20:26 sistpoty ok, now let's make a shared object from this file: 20:26 sistpoty gcc -Wl,-z,defs -Wl,-soname,libexample.so.1 -fPIC -shared example.c -o libexample.so 20:27 sistpoty everyone got it? 20:27 warp10 y 20:27 mok0 + 20:27 sistpoty ok, now let's look again at it with nm 20:28 warp10 wow... 20:29 sistpoty (you can ignore anything with an underscore, that's internal stuff) 20:29 bddebian nm is like objdump? 20:29 slangasek yes 20:29 bddebian ok 20:29 slangasek I might suggest at this point also running 'nm -D libexample.so', for comparison 20:29 sistpoty erm... sorry, we need to do another thing I forgot... let's first strip off the debugging symbols 20:30 sistpoty strip libexample.so 20:30 slangasek ... or that :) 20:30 geser nm: libexample.so: no symbols 20:30 mok0 hehe 20:31 mok0 that's easy :-) 20:31 sistpoty ok, to look at the dynamic symbols, you'll now want nm -D as slangasek suggested 20:32 slangasek right - since we strip binaries by default, 'nm foo.so' in the wild is going to give you empty output 20:32 geser the local symbols aren't listed anymore? 20:32 sistpoty what you'll see is that there are now (apart from some internals) only global symbols left. i.e. everything not defined as "static" 20:32 sistpoty exactly 20:33 sistpoty (side note: the static modifier in c means that the resulting symbol will be a local symbol) 20:34 sistpoty any questions so far? then let's try some other tools on the shared object 20:34 mok0 sistpoty: well, global to the functions in that file 20:34 sistpoty mok0: yes, a local global *g* 20:34 bddebian hrh 20:34 slangasek geser: since they're local, they're by definition not accessible to other things linking to this code; so aside from debugging symbols, which we've used 'strip' to wipe out, there's no reason to take up space by keeping around names for these variables 20:35 sistpoty ok, now let's take a look at the meta-information: 20:35 sistpoty objdump -x libexample.so 20:36 sistpoty this will give lots of info. The most interesting stuff can be found with objdump -p libexample.so as well 20:37 bddebian Who uses anything more than |grep SONAME? ;-) * slangasek raises his hand 20:37 sistpoty one thing that's in there is the SONAME, we'll take a look at it later 20:37 sistpoty the other thing in there is the NEEDED entry (or entries) 20:38 sistpoty the SONAME denotes the ABI-Verison of the shared object... 20:38 sistpoty everything with the same SONAME can be considered to be compatible 20:39 geser if upstream doesn't make a mistake 20:39 bddebian geser: Never happens ;) 20:39 slangasek everything with the same SONAME *will be* considered compatible by ld.so, so it darn well better *be* compatible :) 20:39 sistpoty geser: we'll just see what happens then ;) 20:39 sistpoty the NEEDED entries denote what libraries this shared object needs. These refer to the SONAME of other libraries 20:40 sistpoty I guess everyone knows ldd, let's try that one 20:40 sistpoty ldd libexample.so 20:41 sistpoty ldd will resolve any shared libraries a binary or a shared object needs 20:42 geser is linux-vdso.so.1 provided by the kernel? 20:42 sistpoty so, what's the difference between the NEEDED entries and the output of ldd apart from the pathname? 20:42 slangasek geser: yes, linux-vdso is a bit of Magic 20:43 warp10 ldd output shows three entries, not just one 20:43 geser ldd resolves them recursively * bddebian thinks geser is too smart for this class :) 20:43 sistpoty exactly what geser said :) 20:43 geser bddebian: :P 20:43 sistpoty so you should keep these in mind when dealing with shared objects, as you might want to look at the *direct* dependencies as well 20:44 slangasek yes; for a real world-example, have a look at ldd /usr/lib/libgnome-2.so.0, vs. objdump -p /usr/lib/libgnome-2.so.0 | grep NEEDED 20:45 slangasek so we've looked at the output of nm -D on this object, but nm -D has one weakness as a tool which is not at all obvious if you don't already know what's missing 20:46 slangasek have a look at the output of nm -D libexample.so again 20:46 slangasek now, compare it to the output of readelf -s libexample.so 20:46 slangasek who can spot the difference in the names? 20:47 bddebian The stuff from @@glibc? 20:47 geser you mean the versioned symbols? 20:47 slangasek yep - nm -D doesn't show symbol versions 20:47 mok0 cool 20:48 slangasek so if you want to get at those, you'll want to use objdump -T or readelf -s 20:48 geser what does the "(2)" in "6: 0000000000000000 144 FUNC GLOBAL DEFAULT UND fprintf@GLIBC_2.2.5 (2)" mean? 20:48 slangasek symbol versions are sometimes important, so you'll want to keep these tools in mind -- sometimes, an app/lib will not know the symbol version it's supposed to use, and that indicates a bug! 20:49 slangasek geser: I'm not sure, sorry 20:50 slangasek I'd probably have to look at the readelf source to figure that out, the fields aren't all well-explained in the documentation 20:50 mok0 we can write a dependency resolver from these tools 20:50 slangasek mok0: indeed, dpkg-shlibdeps uses these tools 20:51 sistpoty ok, any more questions so far? 20:51 sistpoty When writing a program, that uses a library, we want to make sure that the API of that library is stable. 20:52 sistpoty If we want to distribute this program, we also want a stable ABI. 20:52 sistpoty stable API means that my program compiles against the library and a newer version of it. 20:52 sistpoty stable ABI means that the symbols stay the same 20:53 mok0 what if there are new symbols? 20:53 sistpoty mok0: of course... I just wanted to correct myself 20:53 sistpoty stable ABI means that there won't get any symbols removed, and their meaning is still the same 20:55 mok0 If you write code that corrects a bug, but the interface remains the same? 20:55 sistpoty mok0: then the ABI and API is stable 20:56 sistpoty (most likely) 20:56 mok0 ... but I would still want that programs exclusively use the fixed version 20:56 sistpoty but let's first have some fun... as some newby upstream started to produce a library... 20:56 geser mok0: if I'm correct you can change the implementation as long as function name, arguments and return type stay the same 20:57 sistpoty mok0: you can do this (as upstream) only, if the library have some version string or date encoded 20:57 mok0 ok 20:57 sistpoty mok0: or by advetising it on your homepage *g* 20:57 mok0 you can bump the minor version number 20:58 sistpoty for the library: yes (I'll come to this part yet) 20:58 chiptoxic how do you tell if a library has a stable API or ABI is it just by watching the version numbers of that library? 20:58 sistpoty chiptoxic: I'd like to postpone this question, as I first want to show you an example 20:59 chiptoxic ok 20:59 sistpoty so please everyone get 20:59 sistpoty if you've got it, extract it and compile it with 20:59 sistpoty make 21:00 sistpoty then install the result (as root) with 21:00 sistpoty make install 21:00 sistpoty (no worries, it will only copy files to the /usr/local/ namespace, and make uninstall removes it again) 21:01 sistpoty everyone got so far? (then me types the commands as well) 21:02 mok0 make PREFIX=. install 21:02 mok0 does it locally 21:03 sistpoty then you might have trouble upgrading the library 21:04 sistpoty (or building an application against it, which we'll do as soon as everyone is finished) * warp10 is done 21:04 sistpoty ok, next step: of course we want s.th. that uses the library, so get 21:05 sistpoty extract that somewhere else and also build the binary with "make" 21:06 sistpoty if you've done that, you should have a cool binary hello_prog, which will print hello. you can even tell it how often it should print hello with the first argument 21:06 sistpoty ./hello_prog 10 21:07 sistpoty everyone got so far yet? 21:07 mok0 error while loading shared libraries: libmyhello.so.1: cannot open shared object file: No such file or directory 21:07 frigaut same here 21:07 geser mok0: sudo ldconfig 21:08 mok0 geser: just doing what the teachers tell me .-) 21:07 warp10 and here too :) 21:07 slangasek heh, did any of the people having this problem install to /usr/local? 21:08 slangasek or did you all install to a different prefix? 21:08 james_w slangasek: /usr/local for me 21:08 slangasek ah, ok 21:08 sistpoty hehe 21:08 frigaut works now after ldconfig 21:08 sistpoty of course I forgot to mention ldconfig 21:08 chiptoxic mine works and i just did what you said and ran ldconfig 21:08 sistpoty (still got it installed from testing *g*) 21:09 mok0 Yay, it says hello to me 10 times 21:09 kdub you have to have /usr/local in your /etc/ld.so.conf of course 21:09 geser sistpoty: "eventually run ldconfig now." 21:09 slangasek kdub: in /etc/ld.so.conf.d/libc.conf actually... :) 21:09 sistpoty geser: hehe, what a nice upstream *g* 21:10 geser yep 21:10 sistpoty now if it prints hello for everyone, let's remove the *library* again with 21:10 sistpoty make uninstall (run as root) 21:11 sistpoty now try again to run the hello_prog. 21:12 sistpoty any results yet? 21:12 geser ./hello_prog: error while loading shared libraries: libmyhello.so.1: cannot open shared object file: No such file or directory 21:12 mok0 boom 21:13 sistpoty great, so (I guess what you expected) it won't work w.o. the library 21:13 sistpoty now upstream has released a new version of the library... I guess you all want hot new stuff? 21:13 sistpoty then get it at http://www.potyra.de/library_packaging/libmyhello-1.0.2.tar.gz 21:13 sistpoty we'll be compiling it again: 21:13 sistpoty make 21:14 sistpoty and install it again (run as root) 21:14 sistpoty make install 21:14 mok0 If you install the library again, it works once more :-) 21:14 sistpoty hehe 21:14 warp10 I don't think so :) 21:15 geser ./hello_prog: symbol lookup error: ./hello_prog: undefined symbol: print_hello 21:15 sistpoty (oh, if you haven't removed installed the new library, you could also try ldd ./hello_prog) 21:16 sistpoty so what happened? 21:16 sistpoty now let's try to make use of the knowledge we gathered so far 21:16 mok0 the application attempts to use the new library 21:17 sistpoty mok0: exactly 21:17 sistpoty let's take a look at the symbols of both shared objects (old library vs. new library) 21:17 mok0 => ABI has changed 21:17 sistpoty excellent! 21:18 sistpoty in the old library, we had the function: T print_hello 21:18 sistpoty which upstream obviously renamed to just: T hello 21:19 sistpoty when you start the program, one of the first steps is that undefined symbols will get resolved * bddebian curses upstream 21:19 sistpoty hehe 21:20 slangasek yeah, I would think twice about packaging any libraries from this upstream ;) 21:20 sistpoty which is done recursively for each shared object that is used * sistpoty removes copyright notices *g* 21:20 mok0 This is why it is wrong to use the program version number for library versions 21:20 bddebian heh 21:20 mok0 which a lot of upstream programmers don't understand 21:21 sistpoty when the symbol lookup can't resolve one symbol.. well you just saw what happens. 21:21 sistpoty ok, what we've seen now is an incompatibility on symbol level. 21:22 sistpoty I hope with the tools you've learned so far, you can easily track those down 21:22 sistpoty -> any removed symbol in a shared library is a problem, *if* the SONAME stays the same 21:23 mok0 so let's change it 21:24 sistpoty mok0: feel free to change it, I guess you can figure this in the Makefile 21:24 mok0 I set major to 2 21:25 albert23 Wouldn't this be an API change, since print_hello is not defined anymore in hello.h? 21:25 albert23 I wouldn't expect this to compile anymore? 21:25 sistpoty albert23: exactly: this is an API change as well 21:26 sistpoty ok, but let's get back to the ABI... 21:27 sistpoty symbols however cannot represent the signature of functions (i.e. number of parameters, type of parameters) 21:27 sistpoty this is part of the ABI as well 21:27 sistpoty if we want to look if this changed, we'll need to dig a little bit deeper 21:27 mok0 Now the program works again, because it finds the first version of the library 21:27 mok0 (I changed MAJOR to 2) 21:28 sistpoty mok0: hehe, so you didn't unstall the old library? 21:28 chiptoxic im not a programmer but is there a way you could put an alias in the code say print_hello is really hello so you dont break the api? or would that just be messy 21:28 mok0 sistpoty: I still have 1.0.1 but I removed 1.0.2 21:28 mok0 The new one is 2.0.1 21:29 sistpoty chiptoxic: you could for example abuse the preprocessor: "define print_hello hello" 21:29 mok0 My experiment shows you can have several versions of the library present 21:29 sistpoty er... #define print_hello hello 21:29 chiptoxic ah cool, thanks 21:29 sistpoty ok, back to the topic... 21:30 sistpoty you can look at the debug information with gdb, so let's run 21:30 sistpoty gdb libmyhello.so 21:30 slangasek mok0: exactly, and this is a key reason why we always use the full soname for the names of our library packages 21:30 geser mok0: and now try the same on windows :) 21:30 sistpoty inside gdb, you can look at the signatures of functions with 21:30 sistpoty info functions 21:31 mok0 slangasek: you mean the major soname ? 21:31 slangasek mok0: the "soname" is the value returned by objdump -p $lib | grep SONAME 21:31 mok0 slangasek: ok 21:31 slangasek and set (hopefully) using the -Wl,-soname option at build time 21:32 sistpoty mok0: the Makefile just puts $(MAJOR) and a name in the soname, but the real soname is in SONAME 21:32 slangasek lintian knows the standard way to map sonames to package names, and warns you if your package is named differently. but of course, we have to take care that upstream is handling their ABI right in the first place! 21:32 sistpoty inside gdb, you can also display the types of variables with 21:32 sistpoty info variables === \sh is now known as \sh_away 21:33 sistpoty (which is uninteresting for libmyhello.so though, since it doesn't define a global variable by itself) 21:33 sistpoty everyone looked at the output of "info functions"? 21:34 mok0 just one: hello(void) 21:34 sistpoty you should see s.th. like "void hello(void);" or "void print_hello(void);" there (depending which version you chose) 21:34 sistpoty yes, so upstream is lazy as well *g* * bddebian files upstream bug 21:35 sistpoty now let's strip the shared object (which wasn't done during the build process): 21:35 sistpoty strip libmyhello.so 21:35 sistpoty (outside gdb again) 21:36 sistpoty and then call gdb libmyhello.so again and look at the functions again 21:36 mok0 :-( 21:36 sistpoty as you can see, these are all gone. 21:36 geser mok0: install the -dbgsym package of it :) 21:37 mok0 heh 21:37 sistpoty that's because these were part of the debug symbols, which have been stripped away 21:37 sistpoty ok, so if we want to find out about the ABI-part of the signatures, it's a little bit tougher, but still doable 21:39 sistpoty if a signature is changed (number of arguments and type of a function), it can lead to different results. Most probably it will segfault, since the library and the application no longer agree on what data they exchange) 21:39 sistpoty an exception to this rule is C++ 21:40 sistpoty in C++ the signature is encoded in the name of a symbol 21:40 sistpoty so if you change an argument, add an argument or remove one, you get a different symbol name 21:41 sistpoty (side note: you can use nm -C to demangle these names back to a human readable signature) 21:41 slangasek or c++filt 21:41 sistpoty any questions so far? 21:42 sistpoty chiptoxic: did that answer your question from some time ago? 21:42 slangasek other side note, checking for ABI changes of this kind by hand is hard and tedious; there is a tool in universe that tries to automate this checking, called icheck 21:42 chiptoxic yea, thanks 21:42 mok0 slangasek: icheck, what package? 21:43 sistpoty slangasek: ah, nice :) 21:43 sistpoty mok0: icheck 21:43 slangasek if you're maintaining a library and want to be careful because your upstream isn't, icheck will let you generate a "manifest" from the old and new -dev packages, and compare them to see if the signatures have changed * chiptoxic cant believe how much im learning :) 21:43 james_w slangasek: how does that compare to check-symbols from the ubuntu-dev-tools package? * mok0 install icheck 21:43 slangasek james_w: icheck examines headers, not symbols 21:44 slangasek james_w: so it's specifically for the case where you're trying to detect the kinds of ABI changes that /don't/ show up in the symbol table * bddebian can't keep up being at work :'-( 21:45 slangasek (doh, check-symbols uses nm -D? Baaad, what did we learn was the weakness of nm -D? :-) 21:45 sistpoty slangasek: since you mentioned ABI changes not showing up in the symbol table, want to say a few words to these? 21:46 slangasek probably, let me see where I put those words 21:47 slangasek right - does everyone here understand why changing the arguments or return type of a function is an ABI change? 21:47 mok0 yes 21:47 slangasek (if everyone knows, there's no sense in me spending time explaining it - but if you don't know, please speak up :) 21:48 warp10 y 21:48 mok0 Well renaming a global variable would show up 21:49 slangasek two people know who care, everyone else is asleep or doesn't want to talk to me ;) 21:49 slangasek sistpoty: back to you 21:49 slangasek :) 21:49 mok0 I just tried icheck on the 2 library versions, 21:50 mok0 but I couldn't get it to work 21:50 sistpoty ok 21:50 mok0 ... "Failed to parse libmyhello.so 21:50 sistpoty mok0: haven't used it myself yet 21:51 mok0 sistpoty: :-) 21:51 sistpoty what we should have learned so far is that if the ABI breaks, you'll need to bump the SONAME 21:51 slangasek mok0: you point it at the headers, not at the library 21:51 mok0 Ah! 21:51 sistpoty however there is yet another case, we didn't consider 21:51 slangasek that's the whole point - the library doesn't have the info you need about the function sigs :) 21:52 sistpoty upstream might put additional functionality in the library 21:52 sistpoty and keep the ABI downwards compatible 21:53 sistpoty in that case, the SONAME would (and should) stay the same, because no program ceases to work with the newer library 21:53 sistpoty however this has one caveat: people who use this library might make use of the new features 21:53 mok0 ... but new programs that use the new functionality? 21:54 sistpoty right, so these programs wouldn't work with the old library but only with the new one (even though the SONAME is the same) 21:54 sistpoty for this, there the SONAME is not sufficient alone. 21:55 sistpoty slangasek: told me that historically the minor version was incremented for this 21:55 sistpoty -: * mok0 also read that 21:55 sistpoty but that won't work if you copy binaries from one system to another (as you don't know about the libraries there) 21:56 sistpoty ok, this pretty much was part 1 -- shared objects 21:56 sistpoty any questions so far? 21:57 mok0 Well, what is the answer to the last problem? 21:57 sistpoty mok0: we'll see that in part 2 :) 21:57 mok0 Arrghh 21:57 warp10 :) 21:57 mok0 It stops at the most exiting part 21:58 mok0 typical of these mini-series :-) }}} {{{ 20:06 sistpoty so who's around for part 2 of the library packaging session? 20:06 albert23 hello sistpoty 20:06 sistpoty hi albert23 20:07 sistpoty first off, there is an excellent guide about debian library packaging. We'll use this one as a reference for this session: 20:07 sistpoty http://www.netfort.gr.jp/~dancer/column/libpkg-guide/libpkg-guide.html 20:09 nixternal thanks sistpoty for the wakeup call :) 20:09 sistpoty hi nixternal :) 20:09 nixternal well howdy 20:09 sistpoty ok, in part 1, we hopefully learned all the basic stuff about shared objects. 20:10 ScottK You wouldn't have a link to the log for that would you? 20:10 nixternal I was just gonna ask, I have a lib I gotta package up :) 20:10 albert23 http://irclogs.ubuntu.com/2008/01/17/%23ubuntu-classroom.html 20:10 sistpoty ScottK: sorry.. no idea if this is publically logged somewhere 20:10 sistpoty thanks albert23 20:11 ScottK albert23: Thanks 20:11 sistpoty now in part 2, we'll be packaging a library by example, and will discuss a few of the caveats 20:12 sistpoty since I'm lazy, let's take libmyhello again from part 1 20:12 sistpoty http://www.potyra.de/library_packaging/libmyhello-1.0.1.tar.gz 20:13 sistpoty everyone got it? 20:13 warp10 y 20:13 hellboy195 y 20:13 albert23 yep 20:13 sistpoty ok, let's start with debianization... unpack it, rename the tarball so that we've got a valid .orig.tar.gz 20:14 sistpoty let's take a look, we'll always need a few files in there, let's start with debian/copyright 20:16 sistpoty put in the usual stuff there (this is not really important for the technical bits of library packaging) 20:17 sistpoty what else do we need... I guess we'll be using debhelper, so let's create a compat in debian/ 20:17 sistpoty everyone got it so far? 20:17 hellboy195 y 20:17 warp10 y 20:18 albert23 y 20:18 sistpoty ok, now let's start with the interesting bits 20:18 sistpoty the control-file 20:19 sistpoty First off comes the usual stuff (I'll pastebin this) 20:19 sistpoty hm... pastebin is kinda slow today :( 20:20 sistpoty ok, I'll paste it right here... pastebin doesn't like me *g* 20:21 sistpoty Source: libmyhello 20:21 sistpoty Section: libdevel 20:21 sistpoty Priority: optional 20:21 sistpoty Maintainer: Your Name 20:21 sistpoty Build-Depends: debhelper (>> 5.0.0) 20:21 sistpoty Standards-Version: 3.7.2.0 20:22 sistpoty for a library, we'll always end up with two packages 20:22 sistpoty two binary packages even 20:22 sistpoty one package contains the shared object(s) 20:23 sistpoty and another one, the -dev package will contain everything you need to develop applications with the shared object 20:24 sistpoty i.e. header-files, eventually a statically linked library, eventually pkconfig files (which specify what to pass to the compiler/linker to link against this library) 20:25 sistpoty so let's create an entry for the -dev package 20:25 sistpoty Package: libmyhello-dev 20:25 sistpoty Architecture: any 20:25 sistpoty Description: myhello library headers 20:25 sistpoty This package contains the development headers 20:25 sistpoty for libmyhello. * ScottK notes sistpoty needs to update to the current standards version... 20:26 sistpoty ScottK: hehe, I'm not up to date 20:27 sistpoty the package containing the shared object will need to be named in a special way: 20:28 sistpoty it must be related to the soname. 20:28 sistpoty the library packaging guide I mentioned contains the rules how it should be named 20:29 sistpoty chapter 5, section 3 20:29 sistpoty remember the soname of libmyhello yet? 20:30 sistpoty anyone? 20:30 warp10 mmm... libmyhello.so.1, maybe? 20:30 sistpoty warp10: exactly 20:31 sistpoty if you wouldn't have remembered, you could of course always use objdump -p to find out 20:33 sistpoty so in this case, the name of the library would be libmyhello1 20:33 sistpoty if you've got a library, that contains more than one shared object 20:33 sistpoty you'll need to create a binary package for each of these 20:33 sistpoty let's add an entry for the binary package 20:34 sistpoty Package: libmyhello1 20:34 sistpoty Architecture: any 20:34 sistpoty Depends: ${shlibs:Depends} 20:34 sistpoty Description: myhello library 20:34 sistpoty This package contains the hello library. 20:35 sistpoty ok. anyone got a clue, why the name of this binary must be related to the SONAME? 20:35 sistpoty this binary package... 20:36 sistpoty anoyne` 20:36 sistpoty +? 20:36 albert23 we want to be able to install multiple versions of the library, when ABI changes 20:36 sistpoty albert23: excellent 20:37 sistpoty so does anyone have an idea why this could be needed? 20:38 warp10 sistpoty: maybe different packages may need different versions of the library? 20:38 sistpoty warp10: this would be one argument, but not the main one. 20:38 sistpoty let's just consider that a very essential library (maybe libc) will get updated 20:39 sistpoty currently, I've got libc6 installed, and I guess almost all packages I've got installed will depend on libc6 20:39 sistpoty suddenly, a new libc7 appears 20:40 sistpoty if it couldn't be installed side-by-side to libc6, that would mean that I had to remove *all* installed programs 20:40 sistpoty or that all programs would immediately break if libc6 were removed by force 20:40 sistpoty that's pretty bad, hm? 20:41 sistpoty (I tried this once when I didn't have a clue... wasn't so funny back then *g*) 20:41 warp10 :) 20:41 sistpoty any questions so far? 20:42 warp10 I have one 20:42 warp10 Why the -dev package doesn't need any Depends: field? 20:42 sistpoty warp10: excellent question... it needs one :) 20:43 sistpoty so, as I wrote earlier, the -dev package is what you install if you want to build programs using this library 20:44 sistpoty so we need to make it depend at least on the library package 20:44 sistpoty let's add the depends line there 20:45 sistpoty the header files in question should always match what's in the shared object 20:45 sistpoty hence we'll need to restrict the version for this dependency 20:46 sistpoty Depends: libmyhello1 (= ${binary:Version}) 20:47 sistpoty however often you'll need additional libraries to compile a program with a specific library 20:47 sistpoty so you'll need to add the corresponding -dev packages there as well. 20:48 sistpoty a good indication should give you the NEEDED entries of the shared object 20:49 sistpoty so you'll just need to find the corresponding -dev package that contains these shared objects 20:50 sistpoty so, what do we need here? 20:51 albert23 NEEDED libc.so.6 20:51 sistpoty great. 20:52 sistpoty so let's find out in which package this is (we'll see a better method later) 20:52 sistpoty just use dpkg -S libc.so.6 20:53 sistpoty hooray, it's libc6 :)... so we'll want libc6-dev 20:54 sistpoty (libc6-dev is often ommitted, since build-essential already depends on it. however it's not wrong to add it) 20:55 sistpoty as you might have noticed, in the case of libc6, the -dev package is not named like the source package 20:55 sistpoty but instead it is named like the binary package + -dev 20:56 sistpoty this is useful, if you want to have more than just one version of the library in the archive 20:56 sistpoty (e.g. because one application needs the old one, and won't build with the new version) 20:56 sistpoty then you'll need to be able to select which -dev package you want 20:57 ScottK There's a very recent thread on adding libc6 on debian-devel that came down pretty strongly in favor of adding it. 20:57 sistpoty if you do this, you should have the -dev package(s) of the different versoin Provide and Conflict to libmyhello-dev package 20:58 sistpoty ScottK: ah, haven't read that one yet 20:58 sistpoty (or maybe I have but forgot *g*) 20:59 sistpoty ok, does everyone have the control file so far? 20:59 albert23 y 20:59 warp10 y 21:00 sistpoty hehe, mine is still missing the depends line *g* 21:01 sistpoty ok 21:01 sistpoty what else do we need... a changelog file. just create one with dch 21:03 sistpoty dch --create 21:03 sistpoty (needed to look this up, thought it always was -c) 21:04 sistpoty everyone got it filled in? 21:04 warp10 y 21:05 albert23 y 21:05 sistpoty ok, then let's start with the rules file 21:06 sistpoty let's see what targets we need to adhere to the policy: clean, build, binary, binary-arch, binary-indep 21:06 sistpoty did I miss one? 21:07 warp10 install? 21:07 ScottK configure? 21:07 slangasek not required by policy :) 21:07 sistpoty yep 21:07 warp10 configure should be optional, right? 21:07 sistpoty hi slangasek btw. * slangasek waves 21:08 warp10 install is optional too? 21:08 sistpoty warp10: libmyhello fortunately doesn't need to be configured, as it doesn't use autotools 21:08 sistpoty warp10: yes 21:09 sistpoty let's start with clean, should be easiest 21:09 sistpoty since we'll use debhelper, we'll first call dh_clean 21:09 sistpoty and then: make clean 21:09 sistpoty to cleanup libmyhello stuff 21:09 sistpoty or, if you prefer make distclean 21:10 sistpoty (which won't make a difference *here*) 21:12 sistpoty then let's get a shot at the build rule 21:12 james_w sistpoty: dh_testroot to start clean as well? 21:13 sistpoty james_w: right, makes sense 21:14 sistpoty ok, build should be easy as well. 21:14 sistpoty just a call to make 21:14 sistpoty any questions so far? 21:15 warp10 n 21:15 albert23 n 21:15 sistpoty ok, then let's go to the binary target 21:16 sistpoty since this is an arch:any package, we'll use the binary-arch target for the job, and have the binary target depend on it 21:17 sistpoty let's add some debhelper stuff 21:18 sistpoty dh_testdir 21:18 sistpoty dh_testroot 21:18 sistpoty dh_installchangelogs 21:18 sistpoty dh_installdocs 21:19 sistpoty dh_install 21:19 sistpoty dh_strip 21:19 sistpoty dh_compress 21:19 sistpoty dh_fixperms 21:20 sistpoty and now an interesting one: dh_makeshlibs 21:20 sistpoty (we'll have a look at it in a few minutes) 21:20 sistpoty dh_shlibdeps 21:20 sistpoty dh_installdeb 21:20 sistpoty dh_gencontrol 21:20 sistpoty dh_md5sums 21:20 sistpoty dh_builddeb 21:21 sistpoty since we'll need to build s.th. before we can install it, we'll add a dependency to build for binary-arch 21:22 sistpoty (a nicer way is to use stamps, but that's a different topic) 21:22 sistpoty now what does dh_makeshlibs do... 21:23 sistpoty as you may have noticed, whenever you put ${shlibs:Depends} in the control file, it will get resolved to the library packages during build 21:23 sistpoty this is done via the shlibs-mechanism 21:23 sistpoty if you've been here in part 1, I guess you could build one yourself 21:24 sistpoty if you look at /var/lib/dpkg/info, you'll find a number of shlibs-files 21:25 sistpoty let's take a look at one 21:26 sistpoty the format is: library-name soname-version dependencies 21:27 sistpoty let's look at /usr/lib/dpkg/info/libgnome2-0.shlibs 21:28 sistpoty compare this to the SONAME of /usr/lib/libgnome-2.so.0 21:28 sistpoty this explains the first two fields 21:29 sistpoty the third one is the package where this shared object can be found in 21:29 sistpoty the job of dh_makeshlibs is to generate such a file for us 21:29 warp10 cool... 21:31 sistpoty and at this point, we can try to answer mok0's question of part 1, what to do if upstream released a new abi compatible version, but programs use this one 21:31 sistpoty since the shlibs file can specify a version string (just look at the gnome shlibs file again) 21:31 sistpoty we can request to have a minimum version of the library 21:32 sistpoty this will get replaced for all packages that use ${shlibs:Depends} and build against our library 21:33 sistpoty so we only need to tell dh_makeshlibs, that a new feature landed in the library, so that it will set version field in the shlibs file right 21:33 sistpoty you can do this with dh_makeshlibs -V 21:33 sistpoty now if anyone has installed an older version of the library, and wants to use the program that needs the new cool features 21:34 sistpoty he will have to upgrade the library via apt 21:34 sistpoty any questions so far? 21:34 albert23 How can we know which library version was the first providing a specific ABI version? 21:35 albert23 Isn't there a risk we set version to high in dh_makeshlibs -V? 21:35 sistpoty albert23: pretty much through the same means that we can find out if the ABI is broken 21:35 albert23 ok 21:36 sistpoty albert23: there is no real risk in Ubuntu to set the version to high 21:36 sistpoty however setting the version not high enough can lead to problems 21:36 albert23 It would make backports more difficult? 21:37 sistpoty not too sure... I don't think so 21:37 sistpoty a backport gets compiled to whatever is in gutsy or feisty 21:37 sistpoty so it will get built against the feisty/gutsy version of the library, which has a different version requirement 21:37 ScottK So if you set it correctly and there isn't a sufficient ABI available, the backport build will, correctly, fail. 21:38 sistpoty well... it doesn't really relate to building, but rather to installin 21:38 sistpoty +g 21:39 sistpoty in order to build against a library, the version (and ABI) is irrelevant. 21:39 sistpoty what matters to build against it is the API 21:39 sistpoty the version rather enforces that users *need* to upgrade the library to a minimum ABI version 21:39 ScottK I guess I meant API then. 21:40 sistpoty so if the API changed, the field won't really be much of a problem, since this means a new ABI in almost all cases 21:40 sistpoty and hence a new SONAME, and a different library package 21:41 sistpoty this version is only relevant if the ABI/API stay the same, but new features got added 21:41 ScottK Ah. RIght. 21:41 sistpoty any further questions? 21:42 warp10 n 21:42 albert23 n 21:42 sistpoty ok, then let's try to fix the rules file and finish the package, shall we? 21:43 sistpoty since we use dh_install, we still need to install the files into debian/tmp/ 21:43 sistpoty let's use PREFIX=$(pwd)/debian/tmp make install for this 21:44 sistpoty if you want, you can put this right at the beginning of binary-arch 21:44 sistpoty or you could add an install rule and have binary-arch depend on it... whatever you prefer 21:46 sistpoty now we'll need to sort which files go into which package 21:47 sistpoty so we want libmyhello1.install and libmyhello-dev.install 21:47 sistpoty the header files will go into the -dev package 21:49 sistpoty bah... back a few lines... (recalled the Makefile wrongly)... PREFIX should of course be $(pwd)/debian/tmp/usr 21:49 sistpoty I guess I should have added DESTDIR or s.th. to libmyhello's makefile 21:50 sistpoty in case we'd have a statically linked library (libmyhello.a), that would go into the -dev package as well. 21:51 sistpoty (only useful if you want to link s.th. statically against it) 21:52 sistpoty what else do we need in the -dev pacakge 21:52 sistpoty the .so symlink should go in there as well 21:53 sistpoty btw: the .so symlink is what the linker will look for if you give the -l parameter 21:53 sistpoty more specifically, if you'd call -lmyhello, it would prepand a lib and add an .so and look for this file (libmyhello.so) 21:54 sistpoty in case there are any other files for development purposes (pkconfig files for example), these should also go in the -dev package 21:54 sistpoty luckily we don't have these 21:56 sistpoty in the library package should be the shared object (of course) and the symlink that's named like the soname 21:56 sistpoty while the symlink itself would also be recreated by ldconfig 21:57 sistpoty including it in the library package has the advantage that it will get deleted if the library is removed 21:57 sistpoty because it's a file of the package 21:58 sistpoty everyone got the .install files? 21:58 albert23 y 21:58 warp10 y 21:59 sistpoty ok, let's give it a shot, and see if it works 21:59 sistpoty just use 21:59 sistpoty fakeroot make -f debian/rules binary 22:00 sistpoty to fix the errors 22:00 sistpoty (like my install files, that where wrong *g*) 22:00 albert23 mine too 22:00 warp10 argh... :-S 22:01 sistpoty did you fix the PREFIX=... make install? 22:01 albert23 y 22:01 warp10 sistpoty: just a wrong install for me too :) 22:01 sistpoty warp10: hehe 22:04 albert23 I think $(pwd) did not work 22:04 albert23 make tried to install in /debian 22:05 sistpoty it should install into debian/tmp/usr/ 22:05 albert23 I got this: PREFIX=/debian/tmp/usr make install 22:06 sistpoty heh, I've got the same which doesn't work as well. but the answer is one line above 22:06 sistpoty PREFIX=debian/tmp/usr make install 22:06 sistpoty those nasty slashes *g* 22:06 warp10 grrrr 22:06 albert23 Yep, just removed the pwd part, that works 22:09 sistpoty hm... I guess I'll need to read the make manual again, I was so sure that $(PWD) exists (or $(pwd)) 22:09 albert23 $(CURDIR) ? 22:09 slangasek $(PWD) exists only if it's set in the environment by the invoking shell 22:10 slangasek $(shell pwd) execs out to call the pwd command, so is rather inefficient 22:10 slangasek $(CURDIR) is the make builtin variable you should use 22:11 sistpoty thanks... I guess I confused this with $(pwd), which I often type in the shell *g* 22:11 slangasek :) 22:11 sistpoty so does everyone's build succeed now? 22:12 albert23 yep, package looks good 22:12 warp10 looks fine! 22:12 sistpoty damn, only mine doesn't build yet *g* 22:13 sistpoty ok, so you've got a source package and a binary 22:13 sistpoty let's run lintian at the binary packages. it will take a second look that we've got the files sorted out correctly 22:14 albert23 clean 22:15 sistpoty excellent! 22:15 sistpoty any questions so far? 22:16 albert23 no, that's pretty clear 22:17 warp10 it's fine. Just wondering if it would be so easy in the real-world packaging :) 22:18 albert23 I guess that strongly depends on upstream 22:18 sistpoty ok, so now what would you do if the ABI of a library changed, but the SONAME didn't? * slangasek smiles 22:19 albert23 complain at upstream 22:19 sistpoty albert23: great, that should always be the first choice 22:19 sistpoty can you imagine, while it's a bad idea, if you bump the SONAME on your own? 22:20 sistpoty (as a packager)? 22:20 albert23 could be risky, as it might conflict with new upstream versions? 22:21 sistpoty that's one argument 22:22 sistpoty but you could append a debian or ubuntu somewhere and change the build scripts, so you could circumvent this 22:22 sistpoty any other arguments against this? 22:22 slangasek it leads to binary incompatibility with other distros 22:22 slangasek but that shouldn't outweigh the problems caused by binary incompatibility with previous releases 22:23 sistpoty also, it leads to binary incompatibility for binary only software 22:23 sistpoty (just imaging to change the SONAME of libc, and look at what breaks in multiverse) 22:24 slangasek well, a workaround for such binary-only software would be to instruct users to create their own local symlinks for the wrong soname 22:25 sistpoty heh 22:25 sistpoty ok, what other interesting points do we have... 22:25 slangasek like I said, the alternative is that you have to break all the /free/ software using the old version on upgrade :) 22:25 sistpoty yeah, it's either bad or worse *g* 22:26 sistpoty ok, what should you do when you upgrade a library? 22:26 slangasek by "upgrade", you mean "package a new version"? 22:26 sistpoty yes 22:27 sistpoty we already learned that we should look out for ABI compatibility, so let's look at the case where we *do* have a new SONAME 22:27 sistpoty and hence a new library package 22:28 sistpoty anyone any ideas? 22:28 slangasek grep -r $oldsover debian/ :) 22:28 albert23 I think we are going to have a problem with the -dev package 22:29 sistpoty albert23: what do you think could get problematic? 22:29 albert23 packages requiring the old ABI will get the new ABI when we would want to rebuild? 22:30 sistpoty exactly (but it's API in this case... compiling *P*rograms->aPi, binaries->aBi) 22:31 sistpoty so you should check which packages actually build-depend on the -dev package. 22:31 sistpoty if there is a large number, you could do local test-builds and see which fail 22:32 sistpoty in case you cannot live yet with the new version alone, you could for example make a different source package and hence have two version of the library in the archive 22:33 sistpoty one thing you might stumble over when dealing with libraries is a lintian warning about rpath 22:34 sistpoty when you link against a library, that has an rpath set, it will tell the loader to look for the shared object only in that very directory 22:34 sistpoty so you can specify -Wl,-rpath=/somewhere and link hello_prog against it 22:35 sistpoty then the loader will look for libmyhello only in /somewhere when hello_prog is started 22:35 sistpoty can anyone imagine, why using rpath for a library is a bad idea? 22:38 albert23 well, software would break if for some reason the library is moved to another directory.... 22:38 sistpoty exactly 22:38 sistpoty and one use-case for moving a library is for example the ia32-libs package on amd64 22:39 sistpoty ok, any questions? 22:39 slangasek (and multiarch! whoo!) 22:40 slangasek albert23, sistpoty: I would note that the general case is that we don't want to continue supporting an old API for a library, even if it means some work has to be done to get the applications ported 22:40 slangasek so it's /usually/ better to have the new library version take over the source package name and the -dev package name, and only reintroduce an oldlibs package as a last resort 22:41 sistpoty thanks for clarifying 22:41 albert23 Well, one question: what would be the best place to look for bugs / qa issues to practice what we learned? 22:42 sistpoty hm... that's a good question indeed 22:42 sistpoty well, one thing is that you could review library packages on REVU 22:43 sistpoty or get your hands dirty and package a library 22:44 sistpoty ok, I guess we're through with the session... slangasek: anything important I forgot or you'd like to add? 22:45 slangasek sistpoty: I only had half an eye on the channel today; I guess you didn't talk about techniques maintainers can use to automatically detect ABI breakage when moving to a new upstream version? 22:45 sistpoty slangasek: nope 22:46 slangasek the dpkg in hardy includes the new dpkg-gensymbols code developed by Raphaƫl Hertzog in Debian; it basically creates a manifest, declaring which symbols were added in which version of the package 22:46 slangasek the /side/ benefit of this is that if you already know which symbols are supposed to be present, you know if any have gone missing 22:47 slangasek so http://qa.debian.org/cgi-bin/mole/seedsymbols is a site that includes automatically generated symbol manifests for all libs in the archive 22:47 slangasek (the Debian archive, that is; most will be applicable to Ubuntu too, obviously) 22:48 slangasek http://wiki.debian.org/UsingSymbolsFiles is a general description of this 22:48 slangasek I still need to use this on my own packages, so I can only give you theoretical insight into this stuff, not much practical :) 22:49 slangasek and everyone's eyes glaze over again ;) 22:50 albert23 Yeah, I guess I will first do some attempts to do the work manually. 22:50 albert23 I have bookmarked those links for later use... 22:51 slangasek one example of this in practice is the zlib1g package 22:51 slangasek which the maintainer, Mark Brown, blogged about as well (syndicated on planet.d.o) 22:52 sistpoty heh, I skipped this post, and wanted to read it later (which I then forgot *g*) 22:52 sistpoty ok, anything else? 22:53 sistpoty then thanks everyone for coming :) }}} This log has been lightly edited for clarity.