Number: 1925
Title: comp.lang.c error: initializer element is not constant
Submitter: Paulo
Date: Thu Apr 15 17:50:13 2010
Subsys: Build/Installation
Version: 2.26.3
System: x86-Other-Windows XP (using cygwin)
Severity: minor
Problem:
Hey guys, I have tried to build graphviz on cygwin with gcc [ --version reports: (GCC) 3.4.4 (cygming special, gdc 0.12, using dmd 0.125) ] and found a problem on file graphviz-2.26.3/lib/gvpr/compile.c at the declaration/definition: Since I'm compiling for cygwin, WIN32 is not defined, and got error on line #83

error: initializer element is not constant, both for gprDisc.mem and gprDisc.id attribute members
   80 #ifdef WIN32
   81 static Agdisc_t gprDisc = { 0, 0, &gprIoDisc };
   82 #else
   83 static Agdisc_t gprDisc = { &AgMemDisc, &AgIdDisc, &gprIoDisc };
   84 #endif

Seems the problem may be due compiler "should" not know where externals AgMemDisc and AgIdDisc will be placed at compile time (despite it doesn't yell 'cause of gprIoDisc which is declared on same module), and that would only be determined at link time, which could be much later if that could be a loadable module...


C90 said this in the constraints section of 6.5.7, "Initialization":
C99 says this in the constraints section of 6.7.8, "Initialization":

well, the solution given for WIN32 conditional code seems to solve the problem, despite I also didn't like to have to initialize it everywhere, have found some sugestions such as defining all global external vars (default static) in a .c module where we may control their order of creation the disadvantage would be gprDisc would be visible in other modules if they also see the extern declaration, but no one has said it must be in a header file, only the interested modules that share these globals need to know about them, externalized on on a header only those that need to be found everywhere)

Anyway, if the codes guarded with conditionals WIN32 were also compiled the problem would be already solved, seems to be the only places that happened. Also would like to suggest if a build version for cygwin could be included on the site.


 2452 /* readG:
 2453  * Read graph from file and initialize
 2454  * dynamic data.
 2455  */
 2456 Agraph_t *readG(Sfio_t * fp)
 2457 {
 2458     Agraph_t *g;
 2459
 2460 #ifdef WIN32
 2461     gprDisc.mem = &AgMemDisc;
 2462     gprDisc.id = &AgIdDisc;
 2463 #endif

...

2473 /* openG: 2474 * Open graph and initialize dynamic data. 2475 */ 2476 Agraph_t *openG(char *name, Agdesc_t desc) 2477 { 2478 Agraph_t *g; 2479 2480 #ifdef WIN32 2481 gprDisc.mem = &AgMemDisc; 2482 gprDisc.id = &AgIdDisc; 2483 #endif


Comments:
[erg] I prefer to keep these strangenesses localized. To me, the ideal solution would use configure to determine if the compilation system supports addresses of external objects in initializers, and wrap the code with a specific preprocessor variable. Given that this problem is very limited, the simplest solution would be to replace #ifdef WIN32 with something like #if WIN32 || CYGWIN. We already use


  #if defined(WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__)

several places in the code.

By the way, during some recent clean up, we lost the related mechanism for lt_preloaded_symbols in dot_builtins.c. This doesn't compile on Windows for the same reason. On Windows, the structure needs to be initialized at runtime.
Fix:
So basically on graphviz-2.26.3/lib/gvpr/compile.c if the code with WIN32 conditionals is made default for any plattform that compiles ok. A better solution could be put all initialization code for globals in a .c module where the order of the creation could be controled by the sequence of declaration/definitions
Owner: *
Status: *