[GRASS-dev] lib/pngdriver Mingw compile error

I've just been experimenting with compiling GRASS under Mingw32 on Windows. Half my time's been spent ripping out Mingw-specific hacks in the Makefiles and configure scripts as they make it impossible to see what's really going on. Anyway it seems to be compiling and running for the most part OK (well as well as can be expected) using shared dlls for the GRASS internal libraries, but am having the following problem with lib/pngdriver (compiler output reproduced below). I might be able to get to the bottom of it but thought perhaps there might be a chance of resolving it much more quickly if posting to the list? A few people have done MinGW compiles now. I'm using libpng 1.2.12.

Paul

sh-2.04$ cd lib/pngdriver
sh-2.04$ make
gcc -shared -o /c/grass/grass6/dist.i686-pc-mingw32/lib/libgrass_pngdriver.dll -
L/c/grass/grass6/dist.i686-pc-mingw32/lib -Wl,--export-dynamic -L/c/grass/lib
    OBJ.i686-pc-mingw32/Box.o OBJ.i686-pc-mingw32/Client.o OBJ.i686-pc-mingw32/Co
lor.o OBJ.i686-pc-mingw32/Color_table.o OBJ.i686-pc-mingw32/Draw_bitmap.o OBJ.i6
86-pc-mingw32/Draw_line.o OBJ.i686-pc-mingw32/Draw_point.o OBJ.i686-pc-mingw32/E
rase.o OBJ.i686-pc-mingw32/Graph_close.o OBJ.i686-pc-mingw32/Graph_set.o OBJ.i68
6-pc-mingw32/Line_width.o OBJ.i686-pc-mingw32/Raster_RGB.o OBJ.i686-pc-mingw32/R
aster_int.o OBJ.i686-pc-mingw32/Respond.o OBJ.i686-pc-mingw32/write.o OBJ.i686-p
c-mingw32/write_ppm.o OBJ.i686-pc-mingw32/write_png.o -lgrass_driver -lgrass_gis
  -lgrass_datetime -lxdr -liberty -lws2_32 -lz -lgrass_gis -lgrass_date
time -lxdr -liberty -lws2_32 -lz -lpng -lz
Info: resolving _NCOLORS by linking to __imp__NCOLORS (auto-import)
Info: resolving _standard_colors_rgb by linking to __imp__standard_colors_rgb (a
uto-import)
Info: resolving _cur_y by linking to __imp__cur_y (auto-import)
Info: resolving _cur_x by linking to __imp__cur_x (auto-import)
Info: resolving _screen_left by linking to __imp__screen_left (auto-import)
Info: resolving _screen_right by linking to __imp__screen_right (auto-import)
Info: resolving _screen_top by linking to __imp__screen_top (auto-import)
Info: resolving _screen_bottom by linking to __imp__screen_bottom (auto-import)
OBJ.i686-pc-mingw32/Color_table.o(.text+0x20f): In function `init_color_table':
c:/grass/grass6/lib/pngdriver/Color_table.c:77: variable 'standard_colors_rgb' c
an't be auto-imported. Please read the documentation for ld's --enable-auto-impo
rt for details.
OBJ.i686-pc-mingw32/Color_table.o(.text+0x223):c:/grass/grass6/lib/pngdriver/Col
or_table.c:77: variable 'standard_colors_rgb' can't be auto-imported. Please rea
d the documentation for ld's --enable-auto-import for details.
collect2: ld returned 1 exit status
make: *** [/c/grass/grass6/dist.i686-pc-mingw32/lib/libgrass_pngdriver.dll] Erro
r 1
sh-2.04$

Paul Kelly wrote:

I've just been experimenting with compiling GRASS under Mingw32 on
Windows. Half my time's been spent ripping out Mingw-specific hacks in the
Makefiles and configure scripts as they make it impossible to see what's
really going on. Anyway it seems to be compiling and running for the most
part OK (well as well as can be expected) using shared dlls for the GRASS
internal libraries, but am having the following problem with lib/pngdriver
(compiler output reproduced below). I might be able to get to the bottom
of it but thought perhaps there might be a chance of resolving it much
more quickly if posting to the list? A few people have done MinGW compiles
now. I'm using libpng 1.2.12.

OBJ.i686-pc-mingw32/Color_table.o(.text+0x20f): In function `init_color_table': c:/grass/grass6/lib/pngdriver/Color_table.c:77: variable 'standard_colors_rgb' can't be auto-imported. Please read the documentation for ld's --enable-auto-import for details.
OBJ.i686-pc-mingw32/Color_table.o(.text+0x223):c:/grass/grass6/lib/pngdriver/Color_table.c:77: variable 'standard_colors_rgb' can't be auto-imported. Please read the documentation for ld's --enable-auto-import for details.

According to the Info file, you need to do something like:

void init_color_table(void)
{
  volatile const struct color_rgb *std_rgb = standard_colors_rgb;
  int colorindex;

  if (true_color)
    init_colors_rgb();
  else
    init_colors_indexed();

  /* Generate lookup for "standard" colors */
  for (colorindex = 1; colorindex <= MAX_COLOR_NUM; colorindex++)
    LIB_assign_standard_color(
      colorindex,
      DRV_lookup_color(
        (int) std_rgb[colorindex].r,
        (int) std_rgb[colorindex].g,
        (int) std_rgb[colorindex].b)) ;
}

The alternative is to add a function to libgis, e.g.:

const struct color_rgb *get_standard_color_rgb(int index)
{
  return &standard_colors_rgb[index];
}

and use that instead of accessing the array directly.

--
Glynn Clements <glynn@gclements.plus.com>

On Tue, 31 Oct 2006, Glynn Clements wrote:

OBJ.i686-pc-mingw32/Color_table.o(.text+0x20f): In function `init_color_table': c:/grass/grass6/lib/pngdriver/Color_table.c:77: variable 'standard_colors_rgb' can't be auto-imported. Please read the documentation for ld's --enable-auto-import for details.
OBJ.i686-pc-mingw32/Color_table.o(.text+0x223):c:/grass/grass6/lib/pngdriver/Color_table.c:77: variable 'standard_colors_rgb' can't be auto-imported. Please read the documentation for ld's --enable-auto-import for details.

According to the Info file, you need to do something like:

void init_color_table(void)
{
  volatile const struct color_rgb *std_rgb = standard_colors_rgb;
  int colorindex;

  if (true_color)
    init_colors_rgb();
  else
    init_colors_indexed();

  /* Generate lookup for "standard" colors */
  for (colorindex = 1; colorindex <= MAX_COLOR_NUM; colorindex++)
    LIB_assign_standard_color(
      colorindex,
      DRV_lookup_color(
        (int) std_rgb[colorindex].r,
        (int) std_rgb[colorindex].g,
        (int) std_rgb[colorindex].b)) ;
}

The alternative is to add a function to libgis, e.g.:

const struct color_rgb *get_standard_color_rgb(int index)
{
  return &standard_colors_rgb[index];
}

and use that instead of accessing the array directly.

Yep the first method worked, thanks. lib/display also had two similar instances that needed changed. Patch included below but I haven't applied it to CVS as I'm not clear on whether this is a wider problem that's better worked around with a new library function or not. Also wondering if there's complications committing to CVS from Windows when the files have DOS line endings.

Next problem is this one here:

sh-2.04$ cd display/drivers/PNG
sh-2.04$ make
gcc -L/c/grass/grass6/dist.i686-pc-mingw32/lib -Wl,--export-dynamic -L/c/grass/
lib -o /c/grass/grass6/dist.i686-pc-mingw32/driver/PNG -L/c/grass/grass6/dis
t.i686-pc-mingw32/lib OBJ.i686-pc-mingw32/main.o -lgrass_pngdriver -lgrass_drive
r -lgrass_gis -lgrass_datetime -lxdr -liberty -lws2_32 -lz -lgrass_gis
  -lgrass_datetime -lxdr -liberty -lws2_32 -lz -lpng -lz -lgrass_drive
r -lgrass_gis -lgrass_datetime -lxdr -liberty -lws2_32 -lz -lgrass_gis
  -lgrass_datetime -lxdr -liberty -lws2_32 -lz -lpng -lz -lxdr -l
iberty -lws2_32 -lz
OBJ.i686-pc-mingw32/main.o(.text+0x188): In function `main':
c:/grass/grass6/display/drivers/PNG/main.c:43: undefined reference to `LIB_main'

collect2: ld returned 1 exit status
make: *** [/c/grass/grass6/dist.i686-pc-mingw32/driver/PNG] Error 1
sh-2.04$

LIB_main() should be defined in libgrass_driver, right? Bit lost on this one. The only other modules with errors are:
GRASS GIS compilation log
-------------------------
Started compilation: Tue Oct 31 09:43:40 WEST 2006
--
Errors in:
/c/grass/grass6/lib/fonts/for_grass
/c/grass/grass6/display/drivers/PNG
/c/grass/grass6/imagery/i.class
/c/grass/grass6/imagery/i.ortho.photo/photo.2image
/c/grass/grass6/imagery/i.ortho.photo/photo.2target
/c/grass/grass6/imagery/i.points
/c/grass/grass6/imagery/i.vpoints
/c/grass/grass6/raster/r.terraflow

So looking fairly good. I was wondering to myself though, to get around the need to use gis.m for monitor output in the native Windows version, might it be a more worthwhile use of time to
a) try and resurrect the libw11 native Windows monitor from GRASS 5, or
b) try and get some simple monitor view window working that reads the output from the PNG driver

I'll think about it.

Paul

Index: display/tran_colr.c

RCS file: /home/grass/grassrepository/grass6/lib/display/tran_colr.c,v
retrieving revision 2.3
diff -u -r2.3 tran_colr.c
--- display/tran_colr.c 18 Apr 2006 05:03:58 -0000 2.3
+++ display/tran_colr.c 31 Oct 2006 08:44:59 -0000
@@ -24,11 +24,12 @@

  int D_translate_color(const char *str )
  {
+ volatile const struct color_name *std_names = standard_color_names;
    int i;

    for (i = 0; i < MAX_COLOR_NAMES; i ++) {
- if (! strcmp (str, standard_color_names[i].name))
- return standard_color_names[i].number ;
+ if (! strcmp (str, std_names[i].name))
+ return std_names[i].number ;
    }

    return(0) ;
@@ -52,6 +53,7 @@

  int D_translate_or_add_color (const char * str, int index)
  {
+ volatile const struct color_rgb *std_rgb = standard_colors_rgb;
         int redi, greeni, bluei;
         int i, preallocated, ret;

@@ -78,9 +80,9 @@
                    the preallocated colors for this color and return the
                    preallocated index on a match. That is what this does: */
                 for (i = 1; i <= MAX_COLOR_NUM; i++)
- if (standard_colors_rgb[i].r == redi &&
- standard_colors_rgb[i].g == greeni &&
- standard_colors_rgb[i].b == bluei)
+ if (std_rgb[i].r == redi &&
+ std_rgb[i].g == greeni &&
+ std_rgb[i].b == bluei)
                                 return i ;

                 /* Add the specified color to the suggested index */
Index: pngdriver/Color_table.c

RCS file: /home/grass/grassrepository/grass6/lib/pngdriver/Color_table.c,v
retrieving revision 1.2
diff -u -r1.2 Color_table.c
--- pngdriver/Color_table.c 19 Sep 2006 10:18:48 -0000 1.2
+++ pngdriver/Color_table.c 31 Oct 2006 08:45:00 -0000
@@ -66,7 +66,9 @@

  void init_color_table(void)
  {
+ volatile const struct color_rgb *std_rgb = standard_colors_rgb;
         int colorindex;
+
         if (true_color)
                 init_colors_rgb();
         else
@@ -77,9 +79,9 @@
                 LIB_assign_standard_color(
                         colorindex,
                         DRV_lookup_color(
- (int) standard_colors_rgb[colorindex].r,
- (int) standard_colors_rgb[colorindex].g,
- (int) standard_colors_rgb[colorindex].b)) ;
+ (int) std_rgb[colorindex].r,
+ (int) std_rgb[colorindex].g,
+ (int) std_rgb[colorindex].b)) ;
  }

  static int get_color_rgb(int r, int g, int b)

Paul Kelly wrote:

Yep the first method worked, thanks. lib/display also had two similar
instances that needed changed. Patch included below but I haven't applied
it to CVS as I'm not clear on whether this is a wider problem that's better
worked around with a new library function or not. Also wondering if
there's complications committing to CVS from Windows when the files have
DOS line endings.

CVS assumes that files are text by default, and should convert line
endings automatically.

Binary files need to be marked as such using the -kb switch; ideally
using "cvs add -kb ..." when the file is first added, although you can
use "cvs admin -kb ..." to flag an existing file as binary.

[Files marked as binary will have -kb in the last field in the
CVS/Entries file; the gui/icons directory has this right, but almost
nothing else did. I've fixed a bunch of obvious cases (GIF/PNG
images).]

Next problem is this one here:

sh-2.04$ cd display/drivers/PNG
sh-2.04$ make
gcc -L/c/grass/grass6/dist.i686-pc-mingw32/lib -Wl,--export-dynamic -L/c/grass/
lib -o /c/grass/grass6/dist.i686-pc-mingw32/driver/PNG -L/c/grass/grass6/dis
t.i686-pc-mingw32/lib OBJ.i686-pc-mingw32/main.o -lgrass_pngdriver -lgrass_drive
r -lgrass_gis -lgrass_datetime -lxdr -liberty -lws2_32 -lz -lgrass_gis
  -lgrass_datetime -lxdr -liberty -lws2_32 -lz -lpng -lz -lgrass_drive
r -lgrass_gis -lgrass_datetime -lxdr -liberty -lws2_32 -lz -lgrass_gis
  -lgrass_datetime -lxdr -liberty -lws2_32 -lz -lpng -lz -lxdr -l
iberty -lws2_32 -lz
OBJ.i686-pc-mingw32/main.o(.text+0x188): In function `main':
c:/grass/grass6/display/drivers/PNG/main.c:43: undefined reference to `LIB_main'

collect2: ld returned 1 exit status
make: *** [/c/grass/grass6/dist.i686-pc-mingw32/driver/PNG] Error 1
sh-2.04$

LIB_main() should be defined in libgrass_driver, right?

Right; lib/driver/main.c.

Bit lost on this

Same here. As it's linking with -lgrass_driver, I have no idea why you
are getting that error. Can you use nm or dlltool to check that the
symbol is actually present in libgrass_driver.

one. The only other modules with errors are:
GRASS GIS compilation log
-------------------------
Started compilation: Tue Oct 31 09:43:40 WEST 2006
--
Errors in:
/c/grass/grass6/lib/fonts/for_grass
/c/grass/grass6/display/drivers/PNG
/c/grass/grass6/imagery/i.class
/c/grass/grass6/imagery/i.ortho.photo/photo.2image
/c/grass/grass6/imagery/i.ortho.photo/photo.2target
/c/grass/grass6/imagery/i.points
/c/grass/grass6/imagery/i.vpoints
/c/grass/grass6/raster/r.terraflow

No surprises there (apart from the PNG driver issue). The i.* stuff
tries to do various low-level stuff related to its terminal-oriented
interface, e.g. signal handling, timeouts etc.

I don't recall what the problem was with the fonts; something to do
with text/binary I/O, maybe?

So looking fairly good. I was wondering to myself though, to get around
the need to use gis.m for monitor output in the native Windows version,
might it be a more worthwhile use of time to
a) try and resurrect the libw11 native Windows monitor from GRASS 5, or

The main problem with monitors on Windows is the use of fork().

"d.mon start=..." runs mon.start using system(). mon.start starts the
driver using execl(), so the driver takes over the mon.start process.
The driver initialises itself then goes into the background by
fork()ing and having the parent exit. At that point, the system() call
in d.mon returns, and d.mon then runs mon.select (unless you used the
-s switch).

This all works because the system("mon.select ...") doesn't return
until the driver has initialised itself and (the child version) is
listening on the socket.

On Windows, there are several problems with this:

1. Native Windows doesn't have fork() or execl().

2. Cygwin's versions didn't work correctly for this purpose on
Win95/98/ME.

3. Cygwin's versions won't work on any version of Windows for the
libW11 driver, as the child process doesn't inherit the various
Windows GUI objects created by the parent (cf X11, where the the only
system object is the connection to the X server).

4. Replacing the execl() with spawnl(_P_DETACH,...) and having the
driver run in the foreground eliminates the above issues, but the
result is that system("mon.start ...") returns before the driver has
initialised itself, so the subsequent mon.select fails.

To make the monitor startup work correctly on Windows, we either need
to add some kind of signalling mechanism, or add code to mon.start
which polls the driver until its ready to accept connections.

That still leaves one more problem:

5. Native windows doesn't support PF_LOCAL (Unix-domain) sockets.

b) try and get some simple monitor view window working that reads the
output from the PNG driver

All of the above issues except #3 apply to all drivers, not just the X
driver (or W11 driver). Using direct rendering will suffice for simple
cases, but you can't combine multiple commands. Also, both the PNG
driver and direct rendering have the limiation that modules which use
the mouse won't work.

--
Glynn Clements <glynn@gclements.plus.com>

On Tue, 31 Oct 2006, Glynn Clements wrote:

Paul Kelly wrote:

Next problem is this one here:

[...]

OBJ.i686-pc-mingw32/main.o(.text+0x188): In function `main':
c:/grass/grass6/display/drivers/PNG/main.c:43: undefined reference to `LIB_main'

collect2: ld returned 1 exit status
make: *** [/c/grass/grass6/dist.i686-pc-mingw32/driver/PNG] Error 1
sh-2.04$

LIB_main() should be defined in libgrass_driver, right?

Right; lib/driver/main.c.

Bit lost on this

Same here. As it's linking with -lgrass_driver, I have no idea why you
are getting that error. Can you use nm or dlltool to check that the
symbol is actually present in libgrass_driver.

It wasn't there! I think the problem is this bit in lib/driver/Makefile:
ifneq ($(HAVE_SOCKET),)
   LIB_OBJS += \
         main.o\
         command.o\
         connect_fifo.o\
         connect_sock.o
endif

$HAVE_SOCKET is empty because the configure script isn't detecting sockets properly. This page: http://www.mingw.org/MinGWiki/index.php/sockets appears to give some useful information on what needs done but I'm not sure if some or any of it has been done already in other parts of GRASS? E.g. how have some people got native Windows GRASS working and not come across this before?

Paul

Paul Kelly wrote:

>> Next problem is this one here:
>>
[...]
>> OBJ.i686-pc-mingw32/main.o(.text+0x188): In function `main':
>> c:/grass/grass6/display/drivers/PNG/main.c:43: undefined reference to `LIB_main'
>>
>> collect2: ld returned 1 exit status
>> make: *** [/c/grass/grass6/dist.i686-pc-mingw32/driver/PNG] Error 1
>> sh-2.04$
>>
>> LIB_main() should be defined in libgrass_driver, right?
>
> Right; lib/driver/main.c.
>
>> Bit lost on this
>
> Same here. As it's linking with -lgrass_driver, I have no idea why you
> are getting that error. Can you use nm or dlltool to check that the
> symbol is actually present in libgrass_driver.

It wasn't there! I think the problem is this bit in lib/driver/Makefile:
ifneq ($(HAVE_SOCKET),)
   LIB_OBJS += \
         main.o\
         command.o\
         connect_fifo.o\
         connect_sock.o
endif

Oops. I forgot to mention that the display drivers simply won't
compile on native Windows. I know that, but for some reason it didn't
register when I was writing my reply.

In my previous message, I mentioned:

That still leaves one more problem:

5. Native windows doesn't support PF_LOCAL (Unix-domain) sockets.

This is the problem.

$HAVE_SOCKET is empty because the configure script isn't detecting sockets
properly. This page: http://www.mingw.org/MinGWiki/index.php/sockets
appears to give some useful information on what needs done but I'm not
sure if some or any of it has been done already in other parts of GRASS?
E.g. how have some people got native Windows GRASS working and not come
across this before?

By ignoring any errors related to the drivers. Drivers don't work on
native Windows; at all. That's why you have to use gis.m, which uses
direct (driver-less) rendering.

--
Glynn Clements <glynn@gclements.plus.com>