playerproject / player

The Player cross-platform robot device interface & server
GNU General Public License v2.0
58 stars 31 forks source link

Compilation error with Fedora player-3.1.0-55.fc40 on ruby bindings #26

Open mtasaka opened 7 months ago

mtasaka commented 7 months ago

So Fedora 40 now defaults to gcc14 (development version). gcc14 defaults to -Werror=incompatible-pointer-types , and now compiling player (on Fedora player-3.1.0-55.fc40) causes compilation error as:

/builddir/build/BUILD/player-release-3-1-0/redhat-linux-build/client_libs/libplayerc/bindings/ruby/playercRUBY_wrap.c: In function ‘_wrap_playerc_blackboard_on_blackboard_event_set’:
/builddir/build/BUILD/player-release-3-1-0/redhat-linux-build/client_libs/libplayerc/bindings/ruby/playercRUBY_wrap.c:56575:23: warning: ‘struct playerc_blackboard’ declared inside parameter list will not be visible outside of this definition or declaration
56575 |   void (*arg2)(struct playerc_blackboard *,player_blackboard_entry_t) = (void (*)(struct playerc_blackboard *,player_blackboard_entry_t)) 0 ;
      |                       ^~~~~~~~~~~~~~~~~~
/builddir/build/BUILD/player-release-3-1-0/redhat-linux-build/client_libs/libplayerc/bindings/ruby/playercRUBY_wrap.c:56575:90: warning: ‘struct playerc_blackboard’ declared inside parameter list will not be visible outside of this definition or declaration
56575 |   void (*arg2)(struct playerc_blackboard *,player_blackboard_entry_t) = (void (*)(struct playerc_blackboard *,player_blackboard_entry_t)) 0 ;
      |                                                                                          ^~~~~~~~~~~~~~~~~~
/builddir/build/BUILD/player-release-3-1-0/redhat-linux-build/client_libs/libplayerc/bindings/ruby/playercRUBY_wrap.c:56575:73: error: initialization of ‘void (*)(struct playerc_blackboard *, player_blackboard_entry_t)’ {aka ‘void (*)(struct playerc_blackboard *, struct player_blackboard_entry)’} from incompatible pointer type ‘void (*)(struct playerc_blackboard *, player_blackboard_entry_t)’ {aka ‘void (*)(struct playerc_blackboard *, struct player_blackboard_entry)’} [-Wincompatible-pointer-types]
56575 |   void (*arg2)(struct playerc_blackboard *,player_blackboard_entry_t) = (void (*)(struct playerc_blackboard *,player_blackboard_entry_t)) 0 ;
      |                                                                         ^
/builddir/build/BUILD/player-release-3-1-0/redhat-linux-build/client_libs/libplayerc/bindings/ruby/playercRUBY_wrap.c:56593:41: error: assignment to ‘void (*)(struct playerc_blackboard *, player_blackboard_entry_t)’ {aka ‘void (*)(struct playerc_blackboard *, struct player_blackboard_entry)’} from incompatible pointer type ‘void (*)(struct playerc_blackboard *, player_blackboard_entry_t)’ {aka ‘void (*)(struct playerc_blackboard *, struct player_blackboard_entry)’} [-Wincompatible-pointer-types]
56593 |   if (arg1) (arg1)->on_blackboard_event = arg2;
      |                                         ^
/builddir/build/BUILD/player-release-3-1-0/redhat-linux-build/client_libs/libplayerc/bindings/ruby/playercRUBY_wrap.c: In function ‘_wrap_playerc_blackboard_on_blackboard_event_get’:
/builddir/build/BUILD/player-release-3-1-0/redhat-linux-build/client_libs/libplayerc/bindings/ruby/playercRUBY_wrap.c:56605:25: warning: ‘struct playerc_blackboard’ declared inside parameter list will not be visible outside of this definition or declaration
56605 |   void (*result)(struct playerc_blackboard *,player_blackboard_entry_t) = 0 ;
      |                         ^~~~~~~~~~~~~~~~~~
/builddir/build/BUILD/player-release-3-1-0/redhat-linux-build/client_libs/libplayerc/bindings/ruby/playercRUBY_wrap.c:56616:29: warning: ‘struct playerc_blackboard’ declared inside parameter list will not be visible outside of this definition or declaration
56616 |   result = (void (*)(struct playerc_blackboard *,player_blackboard_entry_t)) ((arg1)->on_blackboard_event);
      |                             ^~~~~~~~~~~~~~~~~~
/builddir/build/BUILD/player-release-3-1-0/redhat-linux-build/client_libs/libplayerc/bindings/ruby/playercRUBY_wrap.c:56616:10: error: assignment to ‘void (*)(struct playerc_blackboard *, player_blackboard_entry_t)’ {aka ‘void (*)(struct playerc_blackboard *, struct player_blackboard_entry)’} from incompatible pointer type ‘void (*)(struct playerc_blackboard *, player_blackboard_entry_t)’ {aka ‘void (*)(struct playerc_blackboard *, struct player_blackboard_entry)’} [-Wincompatible-pointer-types]
56616 |   result = (void (*)(struct playerc_blackboard *,player_blackboard_entry_t)) ((arg1)->on_blackboard_event);
      |          ^

These warnings / errors are a bit difficult to understand, but the file redhat-linux-build/client_libs/libplayerc/bindings/ruby/playercRUBY_wrap.c generated by swig, then preprocessed, reads:

  26934 # 443 "/builddir/build/BUILD/player-release-3-1-0/redhat-linux-build/client_libs/libplayerc/bindings/ruby/playerc_wrap.h"
  26935 typedef struct {
  26936 
  26937   playerc_device_t info;
  26938 
  26939   void (*on_blackboard_event)(struct playerc_blackboard*, player_blackboard_entry_t);
  26940 
  26941   void *py_private;
  26942 } playerc_blackboard_t;

  30715  typedef playerc_blackboard_t playerc_blackboard;

 103069 static __attribute__ ((__unused__)) VALUE
 103070 _wrap_playerc_blackboard_on_blackboard_event_set(int argc, VALUE *argv, VALUE self) {
 103071   playerc_blackboard *arg1 = (playerc_blackboard *) 0 ;
 103072   void (*arg2)(struct playerc_blackboard *,player_blackboard_entry_t) = (void (*)(struct playerc_blackboard *,player_blackboard_entry_t)) 0 ;

So there is no struct playerc_blackboard forward declaration before _wrap_playerc_blackboard_on_blackboard_event_set, and gcc cannot understand it.

This is because this playercRUBY_wrap.c is generated by parsing header file with client_libs/libplayerc/bindings/python/playerc_swig_parse.py, then converted with swig. The parsed header file client_libs/libplayerc/playerc.h reads:

   1227 typedef struct playerc_blackboard
   1228 {
   1229   /** Device info; must be at the start of all device structures. */
   1230   playerc_device_t info;
   1231   /** Function to be called when a key is updated. */
   1232   void (*on_blackboard_event)(struct playerc_blackboard*, player_blackboard_entry_t);
   1233   /** Kludge to get around python callback issues. */
   1234   void *py_private;
   1235 } playerc_blackboard_t;

So there is struct playerc_blackboard definition, which does self-reference. But then playerc_swig_parse.py reads:

    197     struct=re.compile("""
    198         (?P<decl>typedef\s+struct\s*)\w*\s*  # Declaration <==========================
    199         {(?P<body>.*?)}(?P<footer>\s*        # Body
    200         (?P<name>playerc_\w+?)(_t)?          # Name
    201         \s*;)
    202     """, re.DOTALL|re.VERBOSE)

So this regexp changes the above typedef struct playerc_blackboard line (in playerc.h) to typedef struct , then the generated swig file contains incomplete playerc_blackboard_t declaration.

The fix for this is to do explicit formard declaration for struct playerc_blackboard .