dartprotocol-buffersprotoc

Protobuf dart generation on Mac OS doesn't find protoc-gen-dart


I've installed protoc with homebrew and try to generate dart code with proto files. When I tried a simple case like protoc --dart_out=. test.proto it give me: protoc-gen-dart: program not found or is not executable --dart_out: protoc-gen-dart: Plugin failed with status code 1. But protoc-gen-dart is in my path...

I also tried to specify the path like protoc --dart_out=. --plugin=protoc-gen-dart=~/.pub-cache/bin/protoc-gen-dart ./test.proto but same error...

Anyone know how can I fix this ?

EDIT:

echo | ~/.pub-cache/bin/protoc-gen-dart
Unhandled exception:
InvalidProtocolBufferException: CodedBufferReader encountered a malformed varint.
#0      CodedBufferReader._readRawVarint32 (file:///Users/jaumard/.pub-cache/hosted/pub.dartlang.org/protobuf-0.10.5/lib/src/protobuf/coded_buffer_reader.dart:180:5)
#1      CodedBufferReader.readInt32 (file:///Users/jaumard/.pub-cache/hosted/pub.dartlang.org/protobuf-0.10.5/lib/src/protobuf/coded_buffer_reader.dart:109:22)
#2      CodedBufferReader.readBytes (file:///Users/jaumard/.pub-cache/hosted/pub.dartlang.org/protobuf-0.10.5/lib/src/protobuf/coded_buffer_reader.dart:126:18)
#3      CodedBufferReader.readString (file:///Users/jaumard/.pub-cache/hosted/pub.dartlang.org/protobuf-0.10.5/lib/src/protobuf/coded_buffer_reader.dart:132:39)
#4      _mergeFromCodedBufferReader (file:///Users/jaumard/.pub-cache/hosted/pub.dartlang.org/protobuf-0.10.5/lib/src/protobuf/coded_buffer.dart:158:47)
#5      GeneratedMessage.mergeFromBuffer (file:///Users/jaumard/.pub-cache/hosted/pub.dartlang.org/protobuf-0.10.5/lib/src/protobuf/generated_message.dart:159:5)
#6      new GeneratedMessage.fromBuffer (file:///Users/jaumard/.pub-cache/hosted/pub.dartlang.org/protobuf-0.10.5/lib/src/protobuf/generated_message.dart:31:5)
#7      new CodeGeneratorRequest.fromBuffer (package:protoc_plugin/src/plugin.pb.dart:88:15)
#8      CodeGenerator.generate.<anonymous closure> (file:///Users/jaumard/.pub-cache/hosted/pub.dartlang.org/protoc_plugin-0.10.5/lib/code_generator.dart:66:25)
#9      _RootZone.runUnary (dart:async/zone.dart:1379:54)
#10     _FutureListener.handleValue (dart:async/future_impl.dart:129:18)
#11     Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:642:45)
#12     Future._propagateToListeners (dart:async/future_impl.dart:671:32)
#13     Future._complete (dart:async/future_impl.dart:476:7)
#14     Stream.fold.<anonymous closure> (dart:async/stream.dart:726:18)
#15     _RootZone.runGuarded (dart:async/zone.dart:1302:10)
#16     _BufferingStreamSubscription._sendDone.sendDone (dart:async/stream_impl.dart:389:13)
#17     _BufferingStreamSubscription._sendDone (dart:async/stream_impl.dart:399:15)
#18     _BufferingStreamSubscription._close (dart:async/stream_impl.dart:283:7)
#19     _SyncStreamController._sendDone (dart:async/stream_controller.dart:771:19)
#20     _StreamController._closeUnchecked (dart:async/stream_controller.dart:628:7)
#21     _StreamController.close (dart:async/stream_controller.dart:621:5)
#22     _Socket._onData (dart:io/runtime/binsocket_patch.dart:1728:21)
#23     _RootZone.runUnaryGuarded (dart:async/zone.dart:1314:10)
#24     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:336:11)
#25     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:263:7)
#26     _SyncStreamController._sendData (dart:async/stream_controller.dart:763:19)
#27     _StreamController._add (dart:async/stream_controller.dart:639:7)
#28     _StreamController.add (dart:async/stream_controller.dart:585:5)
#29     new _RawSocket.<anonymous closure> (dart:io/runtime/binsocket_patch.dart:1290:35)
#30     _NativeSocket.issueReadEvent.issue (dart:io/runtime/binsocket_patch.dart:819:18)
#31     _microtaskLoop (dart:async/schedule_microtask.dart:41:21)
#32     _startMicrotaskLoop (dart:async/schedule_microtask.dart:50:5)
#33     _runPendingImmediateCallback (dart:isolate/runtime/libisolate_patch.dart:115:13)
#34     _RawReceivePortImpl._handleMessage (dart:isolate/runtime/libisolate_patch.dart:172:5)

And dtruss output:

 sudo dtruss protoc --dart_out=. --plugin=protoc-gen-dart=~/.pub-cache/bin/protoc-gen-dart ./test.proto -I=.
Password:
dtrace: system integrity protection is on, some features will not be available

SYSCALL(args)            = return
~/.pub-cache/bin/protoc-gen-dart: program not found or is not executable
--dart_out: protoc-gen-dart: Plugin failed with status code 1.
open("/dev/dtracehelper\0", 0x2, 0xFFFFFFFFE5D36050)             = 3 0
ioctl(0x3, 0x80086804, 0x7FFEE5D35E60)           = 0 0
close(0x3)               = 0 0
madvise(0x10A24F000, 0x2000, 0x5)                = 0 0
access("/AppleInternal/XBS/.isChrooted\0", 0x0, 0x0)             = -1 Err#2
bsdthread_register(0x7FFF65DE2438, 0x7FFF65DE2428, 0x2000)               = 1073742047 0
sysctlbyname(kern.bootargs, 0xD, 0x7FFEE5D35170, 0x7FFEE5D35168, 0x0)            = 0 0
ioctl(0x2, 0x4004667A, 0x7FFEE5D353F4)           = 0 0
mprotect(0x10A2E4000, 0x1000, 0x0)               = 0 0
mprotect(0x10A2EB000, 0x1000, 0x0)               = 0 0
mprotect(0x10A2EC000, 0x1000, 0x0)               = 0 0
mprotect(0x10A2F3000, 0x1000, 0x0)               = 0 0
mprotect(0x109ED0000, 0x90, 0x1)                 = 0 0
mprotect(0x109ED2000, 0x1000, 0x1)               = 0 0
mprotect(0x109ED0000, 0x90, 0x3)                 = 0 0
mprotect(0x109ED0000, 0x90, 0x1)                 = 0 0
issetugid(0x0, 0x0, 0x0)                 = 0 0
getentropy(0x7FFEE5D34A40, 0x20, 0x0)            = 0 0
getpid(0x0, 0x0, 0x0)            = 29452 0
stat64("/AppleInternal\0", 0x7FFEE5D355E0, 0x0)          = -1 Err#2
csops(0x730C, 0x7, 0x7FFEE5D35110)               = -1 Err#22
proc_info(0x2, 0x730C, 0xD)              = 64 0
csops(0x730C, 0x7, 0x7FFEE5D34960)               = -1 Err#22
access(".\0", 0x0, 0x0)          = 0 0
stat64("/\0", 0x7FFEE5D33EF8, 0x0)               = 0 0
getattrlist("/usr\0", 0x7FFF65CC0954, 0x7FFEE5D35840)            = 0 0
getattrlist("/usr/local\0", 0x7FFF65CC0954, 0x7FFEE5D35840)              = 0 0
getattrlist("/usr/local/bin\0", 0x7FFF65CC0954, 0x7FFEE5D35840)          = 0 0
getattrlist("/usr/local/bin/protoc\0", 0x7FFF65CC0954, 0x7FFEE5D35840)           = 0 0
readlink("/usr/local/bin/protoc\0", 0x7FFEE5D34C40, 0x400)               = 37 0
getattrlist("/usr/local/Cellar\0", 0x7FFF65CC0954, 0x7FFEE5D35840)               = 0 0
getattrlist("/usr/local/Cellar/protobuf\0", 0x7FFF65CC0954, 0x7FFEE5D35840)              = 0 0
getattrlist("/usr/local/Cellar/protobuf/3.6.1.1\0", 0x7FFF65CC0954, 0x7FFEE5D35840)              = 0 0
getattrlist("/usr/local/Cellar/protobuf/3.6.1.1/bin\0", 0x7FFF65CC0954, 0x7FFEE5D35840)          = 0 0
getattrlist("/usr/local/Cellar/protobuf/3.6.1.1/bin/protoc\0", 0x7FFF65CC0954, 0x7FFEE5D35840)           = 0 0
access("/usr/local/Cellar/protobuf/3.6.1.1/bin/google/protobuf/descriptor.proto\0", 0x0, 0x0)            = -1 Err#2
access("/usr/local/Cellar/protobuf/3.6.1.1/bin/include/google/protobuf/descriptor.proto\0", 0x0, 0x0)            = -1 Err#2
access("/usr/local/Cellar/protobuf/3.6.1.1/include/google/protobuf/descriptor.proto\0", 0x0, 0x0)                = 0 0
access("./test.proto\0", 0x0, 0x0)               = 0 0
open("./test.proto\0", 0x0, 0x2)                 = 3 0
close(0x3)               = 0 0
open("test.proto\0", 0x0, 0x2)           = 3 0
dtrace: error on enabled probe ID 2174 (ID 159: syscall::read:return): invalid kernel access in action #12 at DIF offset 68
dtrace: error on enabled probe ID 2174 (ID 159: syscall::read:return): invalid kernel access in action #12 at DIF offset 68
close(0x3)               = 0 0
pipe(0x0, 0x0, 0x0)              = 3 0
pipe(0x0, 0x0, 0x0)              = 5 0
fork()           = 29455 0
close(0x3)               = 0 0
close(0x6)               = 0 0
sigaction(0xD, 0x7FFEE5D34C78, 0x7FFEE5D34CA0)           = 0 0
select(0x6, 0x7FFEE5D35FE0, 0x7FFEE5D35F60, 0x0, 0x0)            = 1 0
dtrace: error on enabled probe ID 2172 (ID 161: syscall::write:return): invalid kernel access in action #12 at DIF offset 68
close(0x4)               = 0 0
select(0x6, 0x7FFEE5D35FE0, 0x7FFEE5D35F60, 0x0, 0x0)            = 1 0
dtrace: error on enabled probe ID 2174 (ID 159: syscall::read:return): invalid kernel access in action #12 at DIF offset 68
close(0x5)               = 0 0
wait4(0x730F, 0x7FFEE5D34DD8, 0x0)               = 29455 0
sigaction(0xD, 0x7FFEE5D34C78, 0x7FFEE5D34CA0)           = 0 0
getrlimit(0x1008, 0x7FFEE5D36160, 0x0)           = 0 0
dtrace: error on enabled probe ID 2173 (ID 947: syscall::write_nocancel:return): invalid kernel access in action #12 at DIF offset 68
dtrace: error on enabled probe ID 2173 (ID 947: syscall::write_nocancel:return): invalid kernel access in action #12 at DIF offset 68
dtrace: error on enabled probe ID 2173 (ID 947: syscall::write_nocancel:return): invalid kernel access in action #12 at DIF offset 68
dtrace: error on enabled probe ID 2173 (ID 947: syscall::write_nocancel:return): invalid kernel access in action #12 at DIF offset 68

Solution

  • Ok, looks like protoc passes the argument path directly to execve(), which does not expand the ~ character to mean home directory. Try this instead:

    protoc --dart_out=. --plugin=protoc-gen-dart=$HOME/.pub-cache/bin/protoc-gen-dart ./test.proto
    

    In this case $HOME is expanded by the shell before protoc is executed, so it will see the complete path of /Users/yourname/.pub-cache/....


    Below are some steps that were used in debugging, they may help others in the future:

    Your second command looks like it should work:

    protoc --dart_out=. --plugin=protoc-gen-dart=~/.pub-cache/bin/protoc-gen-dart ./test.proto
    

    Perhaps there is something wrong with the executable. You can try executing it directly:

    echo | ~/.pub-cache/bin/protoc-gen-dart
    

    If it is properly executable, you should get an error message similar to "google.protobuf.message.DecodeError: Truncated message." because the data from echo is not what the plugin expects. If you get some other error, that could give clues as to why it is not executable.


    You can also try tracing protoc with dtruss to find out why the plugin execution fails:

    sudo dtruss -f protoc ...
    

    The -f flag is needed to show when protoc tries to start the plugin. There should be a line like this towards the bottom:

    execve("~/.pub-cache/bin/protoc-gen-dart", ..) = -1 Err#2
    

    The error number after Err# tells why the execution failed. In my case, it is number 2, which can be looked up in errno.h file:

    grep 2 /usr/include/sys/errno.h
    
    ...
    #define ENOENT 2 /* No such file or directory */
    ...
    

    Which is because I don't have dart plugin installed. But in your case the error might be something more surprising.