What I Learned from Smoking Clover

I was browsing through the “The New Hackers Dictionary” (http://www.eps.mcgill.ca/jargon/jargon.html), a version of the “Jargon File” (https://en.wikipedia.org/wiki/Jargon_File) when I discovered a entry for Smoking Clover, a display hack attributed to Bill Gosper. I located a copy on SourceForge and downloaded it, and unzipped it into a src directory. Looked routine.

Not.


me@here:~/Projects/Graphics/SmokingClover$ cd src
me@here:~/Projects/Graphics/SmokingClover/src$ make
-g -Wall `gtk-config` --cflags -c -o clover.o clover.c
/bin/sh: 1: gtk-config: not found
In file included from clover.c:1:0:
clover.h:47:21: fatal error: gtk/gtk.h: No such file or directory
compilation terminated.
: recipe for target 'clover.o' failed
make: *** [clover.o] Error 1
me@here:~/Projects/Graphics/SmokingClover/src$/

make did not. The Makefile that comes with the Smoking Clover packages does not make the clover package. Why not?

Well, I know that gtk is installed. What’s wrong with this picture.

What’s in the Makefile?

me@here:~/Projects/Graphics/SmokingClover/src$ cat Makefile
CFLAGS = -g -Wall `gtk-config` --cflags
LIBS = `gtk-config` --libs

SRCS = README COPYING ChangeLog BUGS Makefile *.[ch]

CLOVER_OBJS = clover.o common.o direct.o true.o rgb.o
clover: $(CLOVER_OBJS)
$(CC) $(CFLAGS) -o clover $(CLOVER_OBJS) $(LIBS)
$(CLOVER_OBJS): clover.h Makefile

tar:
tar -cf - $(SRCS) | gzip > clover.tar.gz
clean:
rm -f *.o clover
me@here:~/Projects/Graphics/SmokingClover/src$

Maybe no path to gtk-config …

me@here:~/Projects/Graphics/SmokingClover/src$ locate gtk-config
/usr/share/icons/breeze/apps/32/preferences-gtk-config.svg
/usr/share/icons/breeze-dark/apps/32/preferences-gtk-config.svg

Not promising.

A google or two and still no real answer…

Let’s try something… executing gtk-config.

me@here:~/Projects/Graphics/SmokingClover/src$ gtk-config --cflags
No command 'gtk-config' found, did you mean:
Command 'gts-config' from package 'libgts-bin' (universe)
gtk-config: command not found
me@here:~/Projects/Graphics/SmokingClover/src$

Another google and a hit on StackOverflow provided a hint:

Use pkg-config instead of gtk-config. While the article in Stack Overflow did not say so, gtk-config was for GTK 1.0. GTK 2.0 changed that.

me@here:~/Projects/Graphics/SmokingClover/src$ pkg-config
Must specify package names on the command line

Now we are getting someplace.

me@here:~/Projects/Graphics/SmokingClover/src$ pkg-config gtk-2.0 --cflags
Package gtk-2.0 was not found in the pkg-config search path.
Perhaps you should add the directory containing `gtk-2.0.pc'
to the PKG_CONFIG_PATH environment variable
No package 'gtk-2.0' found

Or better, spell gtk+-2.0 correctly.

me@here:~/Projects/Graphics/SmokingClover/src$ pkg-config gtk+-2.0 --cflags
-pthread -I/usr/include/gtk-2.0 -I/usr/lib/x86_64-linux-gnu/gtk-2.0/include -I/usr/include/gio-unix-2.0/ -I/usr/include/cairo -I/usr/include/pango-1.0 -I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/include/pixman-1 -I/usr/include/libpng12 -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/libpng12 -I/usr/include/pango-1.0 -I/usr/include/harfbuzz -I/usr/include/pango-1.0 -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/freetype2

That’s better. Change the Makefile to include the pkg-config lines

me@here:~/Projects/Graphics/SmokingClover/src$ head Makefile -n 3
CFLAGS = -g -Wall 'pkg-config gtk+-2.0 --cflags`
LIBS = `pkg-config gtk+-2.0 --libs`

me@here:~/Projects/Graphics/SmokingClover/src$ make
cc -g -Wall `pkg-config gtk+-2.0 --cflags` -c -o clover.o clover.c
cc -g -Wall `pkg-config gtk+-2.0 --cflags` -c -o common.o common.c
cc -g -Wall `pkg-config gtk+-2.0 --cflags` -c -o direct.o direct.c
cc -g -Wall `pkg-config gtk+-2.0 --cflags` -c -o true.o true.c
cc -g -Wall `pkg-config gtk+-2.0 --cflags` -c -o rgb.o rgb.c
rgb.c: In function ‘rgb_init’:
rgb.c:28:31: warning: pointer targets in passing argument 1 of ‘gdk_rgb_cmap_new’ differ in signedness [-Wpointer-sign]
rgb_cmap = gdk_rgb_cmap_new (colors, 256);
^
In file included from /usr/include/gtk-2.0/gdk/gdkpixbuf.h:36:0,
from /usr/include/gtk-2.0/gdk/gdkcairo.h:28,
from /usr/include/gtk-2.0/gdk/gdk.h:33,
from /usr/include/gtk-2.0/gtk/gtk.h:32,
from clover.h:47,
from rgb.c:1:
/usr/include/gtk-2.0/gdk/gdkrgb.h:128:13: note: expected ‘guint32 * {aka unsigned int *}’ but argument is of type ‘gint32 * {aka int *}’
GdkRgbCmap *gdk_rgb_cmap_new (guint32 *colors,
^
rgb.c: In function ‘rgb_redraw’:
rgb.c:58:9: warning: pointer targets in assignment differ in signedness [-Wpointer-sign]
countp = counts;
^
cc -g -Wall `pkg-config gtk+-2.0 --cflags` -o clover clover.o common.o direct.o true.o rgb.o `pkg-config gtk+-2.0 --libs`
/usr/bin/ld: direct.o: undefined reference to symbol 'floor@@GLIBC_2.2.5'
//lib/x86_64-linux-gnu/libm.so.6: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
Makefile:8: recipe for target 'clover' failed
make: *** [clover] Error 1
me@here:~/Projects/Graphics/SmokingClover/src$

Close but no cigar.

Looking at the first error found, something called “floor” is undefined at link time. floor … looks like a math function, maybe not to you but I’ve had an interesting life.
A google hit includes the function ceil. A math function. The article suggests you add libm.

You are in a room … you see a libm. take libm

me@here:~/Projects/Graphics/SmokingClover/src$ head -n 3 Makefile
CFLAGS = -g -Wall `pkg-config gtk+-2.0 --cflags`
LIBS = `pkg-config gtk+-2.0 --libs` -lm


me@here:~/Projects/Graphics/SmokingClover/src$ make
cc -g -Wall `pkg-config gtk+-2.0 --cflags` -c -o clover.o clover.c
cc -g -Wall `pkg-config gtk+-2.0 --cflags` -c -o common.o common.c
cc -g -Wall `pkg-config gtk+-2.0 --cflags` -c -o direct.o direct.c
cc -g -Wall `pkg-config gtk+-2.0 --cflags` -c -o true.o true.c
cc -g -Wall `pkg-config gtk+-2.0 --cflags` -c -o rgb.o rgb.c
rgb.c: In function ‘rgb_init’:
rgb.c:28:31: warning: pointer targets in passing argument 1 of ‘gdk_rgb_cmap_new’ differ in signedness [-Wpointer-sign]
rgb_cmap = gdk_rgb_cmap_new (colors, 256);
^
In file included from /usr/include/gtk-2.0/gdk/gdkpixbuf.h:36:0,
from /usr/include/gtk-2.0/gdk/gdkcairo.h:28,
from /usr/include/gtk-2.0/gdk/gdk.h:33,
from /usr/include/gtk-2.0/gtk/gtk.h:32,
from clover.h:47,
from rgb.c:1:
/usr/include/gtk-2.0/gdk/gdkrgb.h:128:13: note: expected ‘guint32 * {aka unsigned int *}’ but argument is of type ‘gint32 * {aka int *}’
GdkRgbCmap *gdk_rgb_cmap_new (guint32 *colors,
^
rgb.c: In function ‘rgb_redraw’:
rgb.c:58:9: warning: pointer targets in assignment differ in signedness [-Wpointer-sign]
countp = counts;
^
cc -g -Wall `pkg-config gtk+-2.0 --cflags` -o clover clover.o common.o direct.o true.o rgb.o `pkg-config gtk+-2.0 --libs` -lm
me@here:~/Projects/Graphics/SmokingClover/src$

WHOA!

make is made!

Smoking Clover now. Or more correctly, the clover executable has been created.

transparent 4 leaf clover in transparent green and magenta
Here is how clover executes on my system

Try it, you’ll like it.

Discussion:

This program is clearly ancient history. What I have discovered since is that gtk-config was the tool used in gtk-1.0 and was replaced in gtk+2.0. No hint of this was in any of the information that I found using the information that I had at the time. Young-in’s, no sense of history.
I also went down a false path (that I cannot seem to reproduce) that required that I add the names of the include files to some of the c header .h files. In reproducing my quest, this did not seem to be necessary. Go figure.

The pointer sign-ed-ness warning may or not be important. It should be fixed. In my experience warnings are there for a reason and the results may be unpredictable. I found some hints as to how to fix it but have not yet gotten to it.

The tag line “No smoke, no odor, not a sound” is from a radio commercial in the late 1960’s from the East Ohio Gas Company touting gas fired domestic incinerators. Refer to the Summary item 5. The jingle was very catchy and memorable. Additional interesting, related stuff