On 2018-03-08 05:18 +0000, Wookey wrote:
I've been packaging libopenCSD for debian. That has resulted in various changes, largely to the makefiles. Most of those changes should go upstream, rather than exist only in the debian version.
I'll post my issues/changes here for discussion so we can decide what is upstreamable.
OK. We get to the harder stuff now.
SONAMEs
libraries should be versioned, so that things which depend on them can say which version they depend on, and users can know when the ABI or API has changed so that they can change their code, or specify the specific one wanted.
libopencsd does not yet have such versioning. A packaged version should have libopencsd.so.0.0.0 (the real library file) libopencsd.so.0 (a link to the real file, used as the soname, and by ldconfig) libopencsd.so (a link to the soname, used to link against) (libopencsd.so.0.0 could also exist if thbere was a need)
i.e libopencsd.so -> libopencsd.so.0 (goes in -dev package) libopencsd.so.0 -> libopencsd.so.0.0.0 (goes in library package) libopencsd.so.0.0.0 (goes in library package)
This is actually quite a fiddly subject. Explained in detail here: http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html (Wheeler) http://man7.org/conf/lca2006/shared_libraries/index.html (Kerrisk) (especially slide6.html) or slightly more accessibly here: https://stackoverflow.com/questions/663209/can-someone-explain-about-linux-l... especially the answer from imolit.
Various conventions for naming are possible, but it makes sense to follow the GNU convention explained by Wheeler, Kerrisk and imolit unless we have good reasons to do something different.
So, the soname of the library is about the library ABI version. That's not the same as the release version, but if we use the same rules when incrementing the release version then these two numbers can be the same, which makes things slightly easier for developers to follow.
So we can either set the ABI version to 0.0.0 and work upwards (as in the examples above), or we can set it to 0.8.0 to match the release version so long as you are happy to increment the 3 parts in line with ABI/API changes. The latter seems most sensible to me, assuming that we are happy with versioning both libraries together?
The versioning can be thought of as Major.Minor.Patch
The rules are described at: http://man7.org/conf/lca2006/shared_libraries/slide5a.html and http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html#AEN135 and in the imolit stackoverflow answer.
Another little wrinkle here is that debian, by convention, puts the major version into the package name, so that packages can explicitly depend on libfoo0 or libfoo1.
So, assuming that's all OK we get down to the mechanics. The existing build does specify an soname in the elf header, but it is unversioned, and the same as the real library filename: $(LINKER) $(LINKER_FLAGS) -o $(LIB_TARGET_DIR)/$(LIB_NAME).so -Wl,-soname,$(LIB_NAME).so $(OBJECTS) so this should be: $(LINKER) $(LINKER_FLAGS) -o $(LIB_TARGET_DIR)/$(LIB_NAME).so.$(SO_VER) -Wl,-soname,$(LIB_NAME).so.$(SO_MAJOR_VER) $(OBJECTS)
I found it hard to get this patch to work right. Because the two libraries are both built in sub-makefiles, I initially set the versions separately in both. I've changed that to do it once at the top level and export them (so long as they will always have the same version). If we decide to use the release version then they should really be parsed out of that rather than just set.
Also it's easy to make the links along with the real library build, but you can't just use $(INSTALL) to install libopencsd.so*, because it always turns links back into files, which is tedious so they have to be 'cp'ed. And the per-library makefiles don't do any installing, only the top-level file.
If the links are made in the obvious way, this reveals a problem with the current makefile design:
all: build_dir $(OBJECTS) mkdir -p $(LIB_TARGET_DIR) $(LIB) $(LIB_FLAGS) $(LIB_TARGET_DIR)/$(LIB_NAME).a $(OBJECTS) - $(LINKER) $(LINKER_FLAGS) -o $(LIB_TARGET_DIR)/$(LIB_NAME).so -Wl,-soname,$(LIB_NAME).so $(OBJECTS) $(SO_LIB_DEPS) + $(LINKER) $(LINKER_FLAGS) -o $(LIB_TARGET_DIR)/$(LIB_NAME).so.$(SO_VER) -Wl,-soname,$(LIB_NAME).so.$(SO_MAJOR_VER) $(OBJ$ + ( cd $(LIB_TARGET_DIR); ln -sf $(LIB_NAME).so.$(SO_VER) $(LIB_NAME).so.$(SO_MAJOR_VER) ) + ( cd $(LIB_TARGET_DIR); ln -sf $(LIB_NAME).so.$(SO_MAJOR_VER) $(LIB_NAME).so )
Using the 'make install' step(which corrects depends on 'libs' causes 'make' to be called on the submakefiles due to the $(LIB_BASE_NAME)_all rule:
$(LIB_TARGET_DIR)/lib$(LIB_BASE_NAME).so: $(LIB_BASE_NAME)_all $(LIB_TARGET_DIR)/lib$(LIB_BASE_NAME).a: $(LIB_BASE_NAME)_all
# single command builds both .a and .so targets in sub-makefile $(LIB_BASE_NAME)_all: mkdir -p $(LIB_TARGET_DIR) cd $(OCSD_ROOT)/build/linux/ref_trace_decode_lib && make
so it tries to build the libraries again, and because the libraries are just built in a PHONY rule, they get built again (harmless but unnecessary), but then the links get created again, which fails unless '-f' is used to force an overwrite. This is all rather unsatisfactory. I'm not sure how you'd prefer to fix this.
Converting it all to autotools is one way, then all this stuff 'just works' :-)
Creating the links entirely in the 'install' stage at the top level.
Fixing the makefiles so they actually only rebuild things that are not already made is another (which is also how make is supposed to work).
I've made the patch by doing the latter, so it's relatively intrusive. The above simple patch also works, at the expense of a double-build, but that is definitely 'wrong'.
(this is not working quite right, so I'll send this mail now, as relevant to the discussion or the first set of patches, and a finished patch later)
Wookey