@@ -32,6 +32,7 @@ fn do_ctest() {
32
32
t if t. contains ( "dragonfly" ) => return test_dragonflybsd ( t) ,
33
33
t if t. contains ( "emscripten" ) => return test_emscripten ( t) ,
34
34
t if t. contains ( "freebsd" ) => return test_freebsd ( t) ,
35
+ t if t. contains ( "haiku" ) => return test_haiku ( t) ,
35
36
t if t. contains ( "linux" ) => return test_linux ( t) ,
36
37
t if t. contains ( "netbsd" ) => return test_netbsd ( t) ,
37
38
t if t. contains ( "openbsd" ) => return test_openbsd ( t) ,
@@ -2946,3 +2947,283 @@ fn which_freebsd() -> Option<i32> {
2946
2947
_ => None ,
2947
2948
}
2948
2949
}
2950
+
2951
+ fn test_haiku ( target : & str ) {
2952
+ assert ! ( target. contains( "haiku" ) ) ;
2953
+
2954
+ let mut cfg = ctest_cfg ( ) ;
2955
+ cfg. flag ( "-Wno-deprecated-declarations" ) ;
2956
+ cfg. define ( "__USE_GNU" , Some ( "1" ) ) ;
2957
+
2958
+ // POSIX API
2959
+ headers ! { cfg:
2960
+ "alloca.h" ,
2961
+ "arpa/inet.h" ,
2962
+ "arpa/nameser.h" ,
2963
+ "arpa/nameser_compat.h" ,
2964
+ "assert.h" ,
2965
+ "bsd_mem.h" ,
2966
+ "complex.h" ,
2967
+ "ctype.h" ,
2968
+ "dirent.h" ,
2969
+ "div_t.h" ,
2970
+ "dlfcn.h" ,
2971
+ "endian.h" ,
2972
+ "errno.h" ,
2973
+ "fcntl.h" ,
2974
+ "fenv.h" ,
2975
+ "fnmatch.h" ,
2976
+ "fts.h" ,
2977
+ "ftw.h" ,
2978
+ "getopt.h" ,
2979
+ "glob.h" ,
2980
+ "grp.h" ,
2981
+ "inttypes.h" ,
2982
+ "iovec.h" ,
2983
+ "langinfo.h" ,
2984
+ "libgen.h" ,
2985
+ "libio.h" ,
2986
+ "limits.h" ,
2987
+ "locale.h" ,
2988
+ "malloc.h" ,
2989
+ "malloc_debug.h" ,
2990
+ "math.h" ,
2991
+ "memory.h" ,
2992
+ "monetary.h" ,
2993
+ "net/if.h" ,
2994
+ "net/if_dl.h" ,
2995
+ "net/if_media.h" ,
2996
+ "net/if_tun.h" ,
2997
+ "net/if_types.h" ,
2998
+ "net/route.h" ,
2999
+ "netdb.h" ,
3000
+ "netinet/icmp6.h" ,
3001
+ "netinet/in.h" ,
3002
+ "netinet/ip.h" ,
3003
+ "netinet/ip6.h" ,
3004
+ "netinet/ip_icmp.h" ,
3005
+ "netinet/ip_var.h" ,
3006
+ "netinet/tcp.h" ,
3007
+ "netinet/udp.h" ,
3008
+ "netinet6/in6.h" ,
3009
+ "nl_types.h" ,
3010
+ "null.h" ,
3011
+ "poll.h" ,
3012
+ "pthread.h" ,
3013
+ "pwd.h" ,
3014
+ "regex.h" ,
3015
+ "resolv.h" ,
3016
+ "sched.h" ,
3017
+ "search.h" ,
3018
+ "semaphore.h" ,
3019
+ "setjmp.h" ,
3020
+ "shadow.h" ,
3021
+ "signal.h" ,
3022
+ "size_t.h" ,
3023
+ "spawn.h" ,
3024
+ "stdint.h" ,
3025
+ "stdio.h" ,
3026
+ "stdlib.h" ,
3027
+ "string.h" ,
3028
+ "strings.h" ,
3029
+ "sys/cdefs.h" ,
3030
+ "sys/file.h" ,
3031
+ "sys/ioctl.h" ,
3032
+ "sys/ipc.h" ,
3033
+ "sys/mman.h" ,
3034
+ "sys/msg.h" ,
3035
+ "sys/param.h" ,
3036
+ "sys/poll.h" ,
3037
+ "sys/resource.h" ,
3038
+ "sys/select.h" ,
3039
+ "sys/sem.h" ,
3040
+ "sys/socket.h" ,
3041
+ "sys/sockio.h" ,
3042
+ "sys/stat.h" ,
3043
+ "sys/statvfs.h" ,
3044
+ "sys/time.h" ,
3045
+ "sys/timeb.h" ,
3046
+ "sys/times.h" ,
3047
+ "sys/types.h" ,
3048
+ "sys/uio.h" ,
3049
+ "sys/un.h" ,
3050
+ "sys/utsname.h" ,
3051
+ "sys/wait.h" ,
3052
+ "syslog.h" ,
3053
+ "tar.h" ,
3054
+ "termios.h" ,
3055
+ "time.h" ,
3056
+ "uchar.h" ,
3057
+ "unistd.h" ,
3058
+ "utime.h" ,
3059
+ "wchar.h" ,
3060
+ "wchar_t.h" ,
3061
+ "wctype.h"
3062
+ }
3063
+
3064
+ // BSD Extensions
3065
+ headers ! { cfg:
3066
+ "pty.h" ,
3067
+ }
3068
+
3069
+ // Native API
3070
+ headers ! { cfg:
3071
+ "kernel/OS.h" ,
3072
+ "kernel/fs_attr.h" ,
3073
+ "kernel/fs_index.h" ,
3074
+ "kernel/fs_info.h" ,
3075
+ "kernel/fs_query.h" ,
3076
+ "kernel/fs_volume.h" ,
3077
+ "kernel/image.h" ,
3078
+ "storage/StorageDefs.h" ,
3079
+ "support/Errors.h" ,
3080
+ "support/SupportDefs.h" ,
3081
+ "support/TypeConstants.h"
3082
+ }
3083
+
3084
+ cfg. skip_struct ( move |ty| {
3085
+ match ty {
3086
+ // FIXME: actually a union
3087
+ "sigval" => true ,
3088
+ // FIXME: locale_t does not exist on Haiku
3089
+ "locale_t" => true ,
3090
+ // FIXME: rusage has a different layout on Haiku
3091
+ "rusage" => true ,
3092
+ // FIXME?: complains that rust aligns on 4 byte boundary, but
3093
+ // Haiku does not align it at all.
3094
+ "in6_addr" => true ,
3095
+ // The d_name attribute is an array of 1 on Haiku, with the
3096
+ // intention that the developer allocates a larger or smaller
3097
+ // piece of memory depending on the expected/actual size of the name.
3098
+ // Other platforms have sensible defaults. In Rust, the d_name field
3099
+ // is sized as the _POSIX_MAX_PATH, so that path names will fit in
3100
+ // newly allocated dirent objects. This breaks the automated tests.
3101
+ "dirent" => true ,
3102
+
3103
+ _ => false ,
3104
+ }
3105
+ } ) ;
3106
+
3107
+ cfg. skip_type ( move |ty| {
3108
+ match ty {
3109
+ // FIXME: locale_t does not exist on Haiku
3110
+ "locale_t" => true ,
3111
+ // These cause errors, to be reviewed in the future
3112
+ "sighandler_t" => true ,
3113
+ "pthread_t" => true ,
3114
+ "pthread_condattr_t" => true ,
3115
+ "pthread_mutexattr_t" => true ,
3116
+ "pthread_rwlockattr_t" => true ,
3117
+ _ => false ,
3118
+ }
3119
+ } ) ;
3120
+
3121
+ cfg. skip_fn ( move |name| {
3122
+ // skip those that are manually verified
3123
+ match name {
3124
+ // FIXME: https://github.com/rust-lang/libc/issues/1272
3125
+ "execv" | "execve" | "execvp" | "execvpe" => true ,
3126
+ // FIXME: does not exist on haiku
3127
+ "open_wmemstream" => true ,
3128
+ "mlockall" | "munlockall" => true ,
3129
+ "tcgetsid" => true ,
3130
+ "cfsetspeed" => true ,
3131
+ // ignore for now, will be part of Haiku R1 beta 3
3132
+ "mlock" | "munlock" => true ,
3133
+ // returns const char * on Haiku
3134
+ "strsignal" => true ,
3135
+
3136
+ _ => false ,
3137
+ }
3138
+ } ) ;
3139
+
3140
+ cfg. skip_const ( move |name| {
3141
+ match name {
3142
+ // FIXME: these constants do not exist on Haiku
3143
+ "DT_UNKNOWN" | "DT_FIFO" | "DT_CHR" | "DT_DIR" | "DT_BLK"
3144
+ | "DT_REG" | "DT_LNK" | "DT_SOCK" => true ,
3145
+ "USRQUOTA" | "GRPQUOTA" => true ,
3146
+ "SIGIOT" => true ,
3147
+ "ARPOP_REQUEST" | "ARPOP_REPLY" | "ATF_COM" | "ATF_PERM"
3148
+ | "ATF_PUBL" | "ATF_USETRAILERS" => true ,
3149
+ // Haiku does not have MAP_FILE, but rustc requires it
3150
+ "MAP_FILE" => true ,
3151
+ // The following does not exist on Haiku but is required by
3152
+ // several crates
3153
+ "FIOCLEX" => true ,
3154
+ // just skip this one, it is not defined on Haiku beta 2 but
3155
+ // since it is meant as a mask and not a parameter it can exist
3156
+ // here
3157
+ "LOG_PRIMASK" => true ,
3158
+ // not defined on Haiku, but [get|set]priority is, so they are
3159
+ // useful
3160
+ "PRIO_MIN" | "PRIO_MAX" => true ,
3161
+ //
3162
+ _ => false ,
3163
+ }
3164
+ } ) ;
3165
+
3166
+ cfg. skip_field ( move |struct_, field| {
3167
+ match ( struct_, field) {
3168
+ // FIXME: the stat struct actually has timespec members, whereas
3169
+ // the current representation has these unpacked.
3170
+ ( "stat" , "st_atime" ) => true ,
3171
+ ( "stat" , "st_atime_nsec" ) => true ,
3172
+ ( "stat" , "st_mtime" ) => true ,
3173
+ ( "stat" , "st_mtime_nsec" ) => true ,
3174
+ ( "stat" , "st_ctime" ) => true ,
3175
+ ( "stat" , "st_ctime_nsec" ) => true ,
3176
+ ( "stat" , "st_crtime" ) => true ,
3177
+ ( "stat" , "st_crtime_nsec" ) => true ,
3178
+
3179
+ // these are actually unions, but we cannot represent it well
3180
+ ( "siginfo_t" , "sigval" ) => true ,
3181
+ ( "sem_t" , "named_sem_id" ) => true ,
3182
+ ( "sigaction" , "sa_sigaction" ) => true ,
3183
+ ( "sigevent" , "sigev_value" ) => true ,
3184
+
3185
+ // skip these enum-type fields
3186
+ ( "thread_info" , "state" ) => true ,
3187
+ ( "image_info" , "image_type" ) => true ,
3188
+ _ => false ,
3189
+ }
3190
+ } ) ;
3191
+
3192
+ cfg. skip_roundtrip ( move |s| match s {
3193
+ // FIXME: for some reason the roundtrip check fails for cpu_info
3194
+ "cpu_info" => true ,
3195
+ _ => false ,
3196
+ } ) ;
3197
+
3198
+ cfg. type_name ( move |ty, is_struct, is_union| {
3199
+ match ty {
3200
+ // Just pass all these through, no need for a "struct" prefix
3201
+ "area_info" | "port_info" | "port_message_info" | "team_info"
3202
+ | "sem_info" | "team_usage_info" | "thread_info" | "cpu_info"
3203
+ | "system_info" | "object_wait_info" | "image_info"
3204
+ | "attr_info" | "index_info" | "fs_info" | "FILE" | "DIR"
3205
+ | "Dl_info" => ty. to_string ( ) ,
3206
+
3207
+ // is actually a union
3208
+ "sigval" => format ! ( "union sigval" ) ,
3209
+ t if is_union => format ! ( "union {}" , t) ,
3210
+ t if t. ends_with ( "_t" ) => t. to_string ( ) ,
3211
+ t if is_struct => format ! ( "struct {}" , t) ,
3212
+ t => t. to_string ( ) ,
3213
+ }
3214
+ } ) ;
3215
+
3216
+ cfg. field_name ( move |struct_, field| {
3217
+ match field {
3218
+ // Field is named `type` in C but that is a Rust keyword,
3219
+ // so these fields are translated to `type_` in the bindings.
3220
+ "type_" if struct_ == "object_wait_info" => "type" . to_string ( ) ,
3221
+ "type_" if struct_ == "sem_t" => "type" . to_string ( ) ,
3222
+ "type_" if struct_ == "attr_info" => "type" . to_string ( ) ,
3223
+ "type_" if struct_ == "index_info" => "type" . to_string ( ) ,
3224
+ "image_type" if struct_ == "image_info" => "type" . to_string ( ) ,
3225
+ s => s. to_string ( ) ,
3226
+ }
3227
+ } ) ;
3228
+ cfg. generate ( "../src/lib.rs" , "main.rs" ) ;
3229
+ }
0 commit comments