GNOME Bugzilla – Bug 565454
Problematic packaging of 0.9.8
Last modified: 2011-01-16 23:37:47 UTC
Gstreamermm 0.9.8 now requires m4 and XML::Parser to do the generation of [ch]*g -> [ch]* during building. Generally this step should be done when preparing the release tarball so that end-user don't have to care about this step.
I understand. m4 is used to during the build process to generate the plug-ins. It's a shortcut I took to automate the generation of the plug-in source files instead of having to write them out by hand. Is this a problem for you (or even in general)? Also, could you elaborate on XML::Parser? Thanks.
The generated files should be distributed in the tarball just as they are for gtkmm.
I see. From the discussion of bug #560601 I was under the impression that not all plug-ins are guaranteed to exist in the target system. This is the relevant comment: > Comment #16 from Sebastian Dröge (reporter, points: 21) >2008-11-16 07:21 UTC [reply] > >Ok, that makes sense then IMHO. One question though, how do you want to wrap >the plugins/elements? I mean, their instance/class struct sizes are not >guaranteed to stay the same as they're not part of the ABI. You could only >create hand-written wrappers that only access the elements via generic >interfaces like GObject properties, gstreamer interfaces, etc. Also >distributors might want to choose to not include some elements, it's not >guaranteed that everybody has audioresample for example :) With this in mind, I thought that it'd be necessary to have the plug-ins generated during the build process. If the plug-ins exist on the system, their source would be generated. If not, that plug-in would not be included during the build and hence not included in the target system. OTOH, if the files are included in the tarball and a plug-in does not exist, what would happen if a user tries to create one of them? I suppose that the creation would simply fail and that would be acceptable. Should things be modified then so that the plug-in source files are included in the tarball even if not all plug-ins are guaranteed to exist in the target system?
> With this in mind, I thought that it'd be necessary to have the plug-ins > generated during the build process. If the plug-ins exist on the system, their > source would be generated. If not, that plug-in would not be included during > the build and hence not included in the target system. But plugins could be installed _after_ the build. I would expect applications need to do some runtime investigation to know whether a plugin is really available. I also generally dislike an API that has so many variations. At the least, we would need some way to #ifdef around the variations in the API. But maybe you have that already.
But couldn't you generate the source for all plugins and only *build* those that are detected on the target system? That's basically what we do for the different cairomm surface types.
(In reply to comment #4) > But plugins could be installed _after_ the build. I would expect applications > need to do some runtime investigation to know whether a plugin is really > available. Yes. Existence of a plug-in is determined in the C API, AFAICT, when 1) there is an attempt to create an element using the plug-in name with gst_element_factory_make[1] or when 2) there is an attempt to load the plug-in with gst_plugin_feature_load[2] after finding it with gst_element_factory_find[3] (A GstElementFactory is also a GstPluginFeature). In both cases a return of NULL from the functions indicates that there is no such plug-in in the system. > > I also generally dislike an API that has so many variations. At the least, we > would need some way to #ifdef around the variations in the API. But maybe you > have that already. The way things work presently is that there are two lists of all possible plug-ins (one for the core plug-ins -- in the gstreamer branch, the other for the base plug-ins -- in the gstreamerbase branch) in the src/Makefile_list_of_hg.am_fragment files. For each plug-in in the lists, the plug-in generator attempts to load the plug-in. If it succeeds, it generates a preliminary .hg file which is run through m4 to generate the gmmproc .hg file and a .ccg file. If the generator fails, empty .hg and .ccg files are generated with a comment in the .hg file saying that the plug-in is not available. The plug-in .hg and .ccg files are not distributed in the tarball but they are installed using nodist_*_SOURCES in the Makefile.am of the *mm directories of the two branches, gstreamer and gstreamerbase. (In reply to comment #5) > But couldn't you generate the source for all plugins and only *build* those > that are detected on the target system? That's basically what we do for the > different cairomm surface types. Building would not be a problem; I tested and building would not fail even if the plug-in does not exist in the system because the C++ code is self-contained, doesn't include any headers from the C API plug-ins (because it can't since these are not public) and generates the necessary structures, etc. to guarantee successful compilation. The problem, I think, is when the wrap_init() functions execute: The plug-in generator generates a *_get_type() function for each plug-in which first makes sure the plug-in is loaded and then gets the GType of the loaded plug-in using gst_element_factory_get_element_type[4]. If there is no plug-in on the system, the _get_type() function would return 0 and this would be a serious problem during initialization. Makes any sense? [1] http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer/html/GstElementFactory.html#gst-element-factory-make [2] http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer/html/GstPluginFeature.html#gst-plugin-feature-load [3] http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer/html/GstElementFactory.html#gst-element-factory-find [4] http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer/html/GstElementFactory.html#gst-element-factory-get-element-type
For a reference of what I'm describing, look at the Gst::FakeSink generated .hg and .ccg files. You'll see the generated structures and _get_type() functions in the .ccg file.
I've been thinking and there may be a couple of solutions: 1) Have the generated files part of the tarball as is done in other *mm projects like gtkmm but then generate the wrap_init() functions based on which plug-ins are present on the build system (This still would require perl processing, I think). 2) Same as above, but not include the plug-ins in the wrap_init()s. After all, the underlying C type of the plug-ins are never available because they're not public so wrapping a C object using Glib::wrap() would be impossible except for the fact that because of the "typedef strct _GstCPluginType GstCPluginType" in the .h file generated by gmmproc, it is available in C++ (see the test-plugin-gen test in tests/). In the C API plug-ins are designed to be referenced only by name with functions such as the ones mentioned before in the footnotes of the previous comments and others in GstPlugin[1] and GstRegistry[2]. If plug-ins are not included in the wrap_inits this would fix this bug altogether. [1] http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer/html/GstPlugin.html [2] http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer/html/GstRegistry.html There's just one observation with 2) above: The user in C++ may want to, for some odd reason, create an element of a plug-in type using the C API and then wrap it with Glib::wrap() in C++ as in the following: GstElement* gst_element = gst_element_factory_make("pluginName", NULL); Glib::RefPtr<Gst::PluginName> element = Glib::wrap( (GstPluginName*) element); But I think this would not be possible with 2). Also, with the above statements, notice the relation between "pluginName" and the C++ type (without the namespace) "PluginName". It's designed to always be so in gstreamermm as it also generally is with the C type though some strange things may occur with the C type such as it changing altogether between releases (see relevant comment[3] in bug #562810). [3] http://bugzilla.gnome.org/show_bug.cgi?id=562810#c5 On a final note, I thought about the comment that gstreamer is very varying, and I understand. Here are my thoughts: I'm completely open to anything such as: 1) Discontinuing development, 2) Passing on development if you all think that someone may better handle the task, 3) Including others that may help to advance development, 4) Having me develop on my own as long as I can and it is useful to others or even 5) passing development over to GStreamer or something like that (though I don't know whether they would want that). I want to make it clear that I don't mind that these choices are made (even if I'm not included) so that it is not difficult to make them. I really have no misgivings about things like this, so they can be decided however best it is convenient. In this way, I wont complicate a decision to include someone else in development or change things around, for example. The reason I began developing gstreamermm is that I thought I would need it for a project that I started, and I think it is nearly at a point where it may be used successfully in this project so this is why I'm open to these decisions; because it is nearly usable. Also, who knows if another API may be used just as well. Again, I'm open.
Sorry for the late response. I have no strong opinion for the packaging, and absolutely no intent to question the development of gstreamermm. As the current approach of source generation, I guess just put m4 and XML::Parser to the build requirement should be enough. (And XML::Parser is required when generating ccg -> cc or hg -> h as it seems.)
> 1) Have the generated files part of the tarball as is done in other *mm > projects like gtkmm but then generate the wrap_init() functions based on which > plug-ins are present on the build system (This still would require perl > processing, I think). There should be ifdefs in the wrap_init.cc just as there are for deprecated or optional API in gtkmm. That would require some changes to the wrap_init.pl script, or a local copy of it, I guess.
(In reply to comment #10) > There should be ifdefs in the wrap_init.cc just as there are for deprecated or > optional API in gtkmm. That would require some changes to the wrap_init.pl > script, or a local copy of it, I guess. Now I think I understand (sorry). I think ifdefs are possible using the gstreamer gst-inspect tool in the configure.ac file and defining C preprocessor symbols for each plug-in available. The symbols can be used in wrap_init.pl for each plug-in as you say. It looks like something similar to what is done for deprecated classes (also as you said) may be necessary for plug-ins, namely a macro similar to _IS_DEPRECATED in gtkmm (maybe _IS_PLUGIN). Would this require a new class macro (like _CLASS_GSTOBJECT) with which to use the "_IS_PLUGIN" macro (as is done with _CLASS_GTKOBJECT) or can the "tagging" macro be placed somewhere in the m4 files and then used with _CLASS_GOBJECT as is done presently? Finally, would it be convenient to do the same thing for plug-ins that don't exist that is done in gtkmm with deprecated classes by having ifdefs in the source files of the plug-ins? In this case, base.m4 in glibmm may have to be modified slightly so that if a gstreamermm plug-in has been marked, the ifdefs are included.
(In reply to comment #11) > It looks like something similar to what is done for deprecated classes (also as > you said) may be necessary for plug-ins, namely a macro similar to > _IS_DEPRECATED in gtkmm (maybe _IS_PLUGIN). Would this require a new class > macro (like _CLASS_GSTOBJECT) with which to use the "_IS_PLUGIN" macro (as is > done with _CLASS_GTKOBJECT) or can the "tagging" macro be placed somewhere in > the m4 files and then used with _CLASS_GOBJECT as is done presently? Nevermind. It looks like an _IS_PLUGIN macro can be included in the m4 files (one named shared.m4) and a new class macro is not required. > Finally, would it be convenient to do the same thing for plug-ins that don't > exist that is done in gtkmm with deprecated classes by having ifdefs in the > source files of the plug-ins? In this case, base.m4 in glibmm may have to be > modified slightly so that if a gstreamermm plug-in has been marked, the ifdefs > are included. Oops, this also is not needed because the plug-ins that don't exist can actually be excluded from the build. I'll post a suggested patch that would fix things a bit later.
Created attachment 125610 [details] [review] Patch to distribute all plug-in sources, but build and install only existing ones. This patch modifies build files, etc. so that the generation of all the plug-ins occurs and only in maintainer mode. All plug-in sources are distributed, but only existing plug-ins are built and installed. I must apologize for not understanding what Murray and Jonathon tried to explain (I'm a little dense; sorry). It turns out that I was mixing up how building works in maintainer mode (where autogen.sh is used) and how building works in non-maintainer mode (where users use configure, which I've used before, but did not make the distinction until recently). With this patch things will work as what happens in other *mm modules like gtkmm, for example. Plug-ins are never generated in standard mode (only in maintainer mode) and only built if they exist. I've also filed a parallel bug about modifying generate_wrap_init.pl on which this bug depends.
I've commited the proposed patch a long with a local copy of generate_wrap_init.pl (from bug #566249) to fix this bug.