gpb เป็นคอมไพเลอร์สำหรับไฟล์คำจำกัดความบัฟเฟอร์โปรโตคอลของ Google สำหรับ Erlang
ทางลัด: เอกสาร API ~ gpb บน hex.pm
สมมติว่าเรามีไฟล์ protobuf x.proto
message Person {
required string name = 1 ;
required int32 id = 2 ;
optional string email = 3 ;
}
เราสามารถสร้างโค้ดสำหรับคำจำกัดความนี้ได้หลายวิธี ที่นี่เราใช้เครื่องมือบรรทัดคำสั่ง สำหรับข้อมูลเกี่ยวกับการรวมเข้ากับเหล็กเส้น โปรดดูเพิ่มเติมด้านล่าง
# .../gpb/bin/protoc-erl -I. x.proto
ตอนนี้เรามี x.erl
และ x.hrl
ขั้นแรกเราคอมไพล์มันแล้วลองทดสอบในเชลล์ Erlang:
# erlc -I.../gpb/include x.erl
# erl
Erlang/OTP 19 [erts-8.0.3] [source] [64-bit] [smp:12:12] [async-threads:10] [kernel-poll:false]
Eshell V8.0.3 (abort with ^G)
1> rr("x.hrl").
['Person']
2> x:encode_msg(#'Person'{ name = " abc def " , id = 345 , email = " [email protected] " }).
<< 10 , 7 , 97 , 98 , 99 , 32 , 100 , 101 , 102 , 16 , 217 , 2 , 26 , 13 , 97 , 64 , 101 ,
120 , 97 , 109 , 112 , 108 , 101 , 46 , 99 , 111 , 109 >>
3 > Bin = v ( - 1 ).
<< 10 , 7 , 97 , 98 , 99 , 32 , 100 , 101 , 102 , 16 , 217 , 2 , 26 , 13 , 97 , 64 , 101 ,
120 , 97 , 109 , 112 , 108 , 101 , 46 , 99 , 111 , 109 >>
4 > x : decode_msg ( Bin , 'Person' ).
# 'Person' { name = " abc def " , id = 345 , email = " [email protected] " }
ใน Erlang เชลล์ rr("x.hrl")
อ่านคำจำกัดความของเร็กคอร์ด และ v(-1)
อ้างอิงค่าหนึ่งขั้นตอนก่อนหน้าในประวัติ
ประเภทโปรโตบัฟ | ประเภทเออร์แลง |
---|---|
สองเท่าลอย | ลอย() | อนันต์ | '-อนันต์' | น่าน เมื่อเข้ารหัสจะยอมรับจำนวนเต็มเช่นกัน |
int32, int64 uint32, uint64 sint32, sint64 แก้ไข 32, แก้ไข 64 sfixed32, sfixed64 | จำนวนเต็ม() |
บูล | จริง | เท็จ เมื่อเข้ารหัส จะยอมรับจำนวนเต็ม 1 และ 0 เช่นกัน |
แจกแจง | อะตอม() enums ที่ไม่รู้จักถอดรหัสเป็นจำนวนเต็ม () |
ข้อความ | บันทึก (ดังนั้น tuple()) หรือ map() หากระบุตัวเลือก map (-maps) |
เชือก | สตริงยูนิโค้ด ดังนั้นรายการจำนวนเต็ม หรือ binary() หากระบุตัวเลือก strings_as_binaries (-strbin) เมื่อทำการเข้ารหัส iolists ก็ได้รับการยอมรับเช่นกัน |
ไบต์ | ไบนารี() เมื่อทำการเข้ารหัส iolists ก็ได้รับการยอมรับเช่นกัน |
หนึ่งในนั้น | {ChosenFieldName, ค่า} หรือ ChosenFieldName => ค่า หากระบุตัวเลือก {maps_oneof,flat} (-maps_oneof flat) |
แผนที่<_,_> | รายการที่ไม่เรียงลำดับของ 2-tuples, [{Key,Value}] หรือ map() หากระบุตัวเลือก map (-maps) |
ฟิลด์ที่ซ้ำจะแสดงเป็นรายการ
ช่องที่ไม่บังคับจะแสดงเป็นค่าหรือ undefined
หากไม่ได้ตั้งค่า อย่างไรก็ตาม สำหรับแผนที่ หากตัวเลือก maps_unset_optional
ถูกตั้งค่าเป็น omitted
ค่าทางเลือกที่ไม่ได้ตั้งค่าจะถูกละเว้นจากแผนที่ แทนที่จะถูกตั้งค่าเป็น undefined
เมื่อเข้ารหัสข้อความ เมื่อถอดรหัสข้อความ แม้จะตั้ง maps_unset_optional
เป็น omitted
ก็ตาม ค่าเริ่มต้นจะถูกตั้งค่าในแผนที่ที่ถอดรหัส
message m1 {
repeated uint32 i = 1 ;
required bool b = 2 ;
required eee e = 3 ;
required submsg sub = 4 ;
}
message submsg {
required string s = 1 ;
required bytes b = 2 ;
}
enum eee {
INACTIVE = 0 ;
ACTIVE = 1 ;
}
# m1 { i = [ 17 , 4711 ],
b = true ,
e = 'ACTIVE' ,
sub = # submsg { s = " abc " ,
b = << 0 , 1 , 2 , 3 , 255 >>}}
% % If compiled to with the option maps:
#{ i => [ 17 , 4711 ],
b => true ,
e => 'ACTIVE' ,
sub => #{ s => " abc " ,
b => << 0 , 1 , 2 , 3 , 255 >>}}
message m2 {
optional uint32 i1 = 1 ;
optional uint32 i2 = 2 ;
}
# m2 { i1 = 17 } % i2 is implicitly set to undefined
% % With the maps option
#{ i1 => 17 }
% % With the maps option and the maps_unset_optional set to present_undefined:
#{ i1 => 17 ,
i2 => undefined }
โครงสร้างนี้ปรากฏตัวครั้งแรกใน Google protobuf เวอร์ชัน 2.6.0
message m3 {
oneof u {
int32 a = 1 ;
string b = 2 ;
}
}
ฟิลด์ oneof จะเป็นตัวเลือกเสมอโดยอัตโนมัติ
# m3 { u = { a , 17 }}
# m3 { u = { b , " hello " }}
# m3 {} % u is implicitly set to undefined
% % With the maps option
#{ u => { a , 17 }}
#{ u => { b , " hello " }}
#{} % If maps_unset_optional = omitted (default)
#{ u => undefined } % With maps_unset_optional set to present_undefined
% % With the {maps_oneof,flat} option (requires maps_unset_optional = omitted)
#{ a => 17 }
#{ b => " hello " }
#{}
อย่าสับสนกับแผนที่ Erlang โครงสร้างนี้ปรากฏครั้งแรกใน Google protobuf เวอร์ชัน 3.0.0 (สำหรับทั้งไวยากรณ์ proto2
และ proto3
)
message m4 {
map < uint32 , string > f = 1 ;
}
สำหรับบันทึก ลำดับของรายการจะไม่ถูกกำหนดเมื่อทำการถอดรหัส
# m4 { f = []}
# m4 { f = [{ 1 , " a " }, { 2 , " b " }, { 13 , " hello " }]}
% % With the maps option
#{ f => #{}}
#{ f => #{ 1 => " a " , 2 => " b " , 13 => " hello " }}
default
ข้อมูลนี้อธิบายวิธีการถอดรหัสสำหรับฟิลด์ตัวเลือกที่ไม่มีอยู่ในไบนารี่เพื่อถอดรหัส
เอกสารประกอบสำหรับ Google protobuf ระบุว่าการถอดรหัสเหล่านี้เป็นค่าเริ่มต้นหากระบุไว้ หรือมิฉะนั้นเป็นค่าเริ่มต้นเฉพาะประเภทของฟิลด์ โค้ดที่สร้างโดยคอมไพเลอร์ protobuf ของ Google ยังมีเมธอด has_<field>()
เพื่อให้สามารถตรวจสอบว่ามีฟิลด์อยู่จริงหรือไม่
อย่างไรก็ตาม ใน Erlang วิธีธรรมชาติในการตั้งค่าและอ่านฟิลด์คือเพียงใช้ไวยากรณ์สำหรับบันทึก (หรือแผนที่) และไม่เหลือวิธีที่ดีในการถ่ายทอดว่ามีฟิลด์นั้นอยู่หรือไม่ และในเวลาเดียวกันเพื่ออ่าน ค่าเริ่มต้น
ดังนั้นแนวทางใน gpb
คือคุณต้องเลือก: อย่างใดอย่างหนึ่งหรือ โดยปกติ คุณสามารถดูได้ว่ามีฟิลด์ตัวเลือกหรือไม่ เช่น โดยการตรวจสอบว่าค่านั้น undefined
หรือไม่ แต่มีตัวเลือกสำหรับคอมไพลเลอร์ในการถอดรหัสเป็นค่าเริ่มต้นแทน ซึ่งในกรณีนี้ คุณจะสูญเสียความสามารถในการดูว่ามีฟิลด์อยู่หรือไม่ ตัวเลือกคือ defaults_for_omitted_optionals
และ type_defaults_for_omitted_optionals
สำหรับการถอดรหัสเป็นค่า default=<x>
หรือเป็นค่าดีฟอลต์เฉพาะประเภทตามลำดับ
มันทำงานในลักษณะนี้:
message o1 {
optional uint32 a = 1 [ default = 33 ];
optional uint32 b = 2 ; // the type-specific default is 0
}
เมื่อรับข้อมูลไบนารี <<>>
นั่นคือไม่มีฟิลด์ a
หรือ b
อยู่ ดังนั้นการเรียก decode_msg(Input, o1)
ส่งผลให้:
# o1 { a = undefined , b = undefined } % None of the options
# o1 { a = 33 , b = undefined } % with option defaults_for_omitted_optionals
# o1 { a = 33 , b = 0 } % with both defaults_for_omitted_optionals
% and type_defaults_for_omitted_optionals
# o1 { a = 0 , b = 0 } % with only type_defaults_for_omitted_optionals
ทางเลือกสุดท้ายอาจไม่มีประโยชน์มากนัก แต่ก็ยังเป็นไปได้ และนำไปปฏิบัติให้ครบถ้วน
การอ้างอิงของ Google
สำหรับ proto3 ไม่ required
หรือ default=<x>
สำหรับฟิลด์ เว้นแต่จะทำเครื่องหมายด้วย optional
ฟิลด์สเกลาร์ สตริง และไบต์ทั้งหมดจะเป็นทางเลือกโดยปริยาย ในการถอดรหัส หากฟิลด์ดังกล่าวขาดหายไปในไบนารี่ที่จะถอดรหัส ฟิลด์เหล่านี้จะถอดรหัสเป็นค่าเริ่มต้นเฉพาะประเภทเสมอ ในการเข้ารหัส ฟิลด์ดังกล่าวจะรวมอยู่ในผลลัพธ์ไบนารีที่เข้ารหัสเท่านั้น หากฟิลด์เหล่านั้นมีค่าแตกต่างจากค่าเริ่มต้นเฉพาะประเภท แม้ว่าฟิลด์ทั้งหมดจะเป็นทางเลือกโดยปริยาย แต่ก็อาจกล่าวได้ว่าในระดับแนวคิด ฟิลด์ดังกล่าวทั้งหมดจะมีค่าเสมอ ในการถอดรหัส ไม่สามารถระบุได้ว่าระหว่างการเข้ารหัสนั้น มีค่าอยู่ --- มีค่าเฉพาะประเภท --- หรือไม่
ช่องที่ทำเครื่องหมายว่าเป็น optional
จะแสดงในลักษณะเดียวกับไวยากรณ์ proto2 ในบันทึก ฟิลด์จะมีค่า undefined
หากไม่ได้ตั้งค่าไว้ และในแผนที่ ฟิลด์นั้นจะไม่ปรากฏหากไม่ได้ตั้งค่าไว้
คำแนะนำที่ฉันเคยเห็นหากคุณต้องการตรวจหาข้อมูลที่ "หายไป" คือการกำหนดฟิลด์ has_<field>
บูลีน และตั้งค่าอย่างเหมาะสม อีกทางเลือกหนึ่งคือการใช้ข้อความ wrapper ที่รู้จักกันดี
ช่องที่เป็นข้อความย่อยและช่องใดช่องหนึ่ง ไม่มีค่าเริ่มต้นเฉพาะประเภทใดๆ ฟิลด์ข้อความย่อยที่ไม่ได้ตั้งค่าไว้จะเข้ารหัสแตกต่างจากฟิลด์ข้อความย่อยที่ตั้งค่าเป็นข้อความย่อย และจะถอดรหัสต่างกัน สิ่งนี้จะยังคงอยู่แม้ว่าข้อความย่อยจะไม่มีฟิลด์ก็ตาม มันทำงานคล้ายกันเล็กน้อยสำหรับฟิลด์ใดฟิลด์หนึ่ง ไม่มีการตั้งค่าฟิลด์ทางเลือกใดฟิลด์หนึ่ง หรือฟิลด์ใดฟิลด์หนึ่งตั้งค่าไว้ รูปแบบที่เข้ารหัสจะแตกต่างกัน และเมื่อถอดรหัสก็เป็นไปได้ที่จะบอกความแตกต่างได้
แยกวิเคราะห์ไฟล์คำจำกัดความบัฟเฟอร์โปรโตคอลและสามารถสร้าง:
คุณสมบัติของไฟล์คำจำกัดความบัฟเฟอร์โปรโตคอล: gpb รองรับ:
packed
และ default
สำหรับฟิลด์allow_alias
enum (ถือว่าตั้งค่าเป็น True เสมอ)oneof
(แนะนำใน protobuf 2.6.0)map<_,_>
(แนะนำใน protobuf 3.0.0)gpb อ่านแต่ไม่สนใจ:
packed
หรือ default
GPB ไม่รองรับ:
ลักษณะของ GPB:
bytes
ได้ตามต้องการหรือแบบมีเงื่อนไข เพื่อให้ระบบรันไทม์ปล่อยไบนารีข้อความขนาดใหญ่ขึ้นpackage
ได้โดยใส่ชื่อของแพ็กเกจไว้หน้าข้อความทุกประเภทที่มีอยู่ (หากกำหนดไว้) ซึ่งมีประโยชน์ในการหลีกเลี่ยงการขัดแย้งกันของชื่อประเภทข้อความในแพ็กเกจต่างๆ โปรดดูอ็อพชัน use_packages
หรืออ็อพชันบรรทัดรับคำสั่ง -pkgs
#field{}
ใน gpb.hrl สำหรับฟังก์ชัน get_msg_defs
แต่เป็นไปได้ที่จะหลีกเลี่ยง การพึ่งพานี้โดยใช้ตัวเลือก defs_as_proplists
หรือ -pldefs
ด้วยวิปัสสนา
gpb สร้างฟังก์ชันบางอย่างสำหรับตรวจสอบข้อความ enums และบริการ:
get_msg_defs()
(หรือ get_proto_defs()
หากตั้งค่า introspect_get_proto_defs
), get_msg_names()
, get_enum_names()
find_msg_def(MsgName)
และ fetch_msg_def(MsgName)
find_enum_def(MsgName)
และ fetch_enum_def(MsgName)
enum_symbol_by_value(EnumName, Value)
,enum_symbol_by_value_<EnumName>(Value)
, enum_value_by_symbol(EnumName, Enum)
และ enum_value_by_symbol_<EnumName>(Enum)
get_service_names()
, get_service_def(ServiceName)
, get_rpc_names(ServiceName)
find_rpc_def(ServiceName, RpcName)
, fetch_rpc_def(ServiceName, RpcName)
นอกจากนี้ยังมีฟังก์ชันบางอย่างสำหรับการแปลระหว่างชื่อที่มีคุณสมบัติครบถ้วนและชื่อภายใน สิ่งเหล่านี้จะนำตัวเลือกการเปลี่ยนชื่อมาพิจารณาด้วย อาจมีประโยชน์เช่นกับการสะท้อน grpc
fqbin_to_service_name(<<"Package.ServiceName">>)
และ service_name_to_fqbin('ServiceName')
fqbins_to_service_and_rpc_name(<<"Package.ServiceName">>, <<"RpcName">>)
และ service_and_rpc_name_to_fqbins('ServiceName', 'RpcName')
fqbin_to_msg_name(<<"Package.MsgName">>)
และ msg_name_to_fqbin('MsgName')
fqbin_to_enum_name(<<"Package.EnumName">>)
และ enum_name_to_fqbin('EnumName')
นอกจากนี้ยังมีฟังก์ชันบางอย่างสำหรับการสอบถามว่าโปรโตชนิดใดเป็นของประเภทใด แต่ละประเภทเป็นของ "name"
บางส่วนซึ่งเป็นสตริง ซึ่งโดยปกติจะเป็นชื่อไฟล์ นามสกุล sans เช่น "name"
หากไฟล์ proto คือ "name.proto"
get_all_proto_names() -> ["name1", ...]
get_msg_containment("name") -> ['MsgName1', ...]
get_pkg_containment("name") -> 'Package'
get_service_containment("name") -> ['Service1', ...]
get_rpc_containment("name") -> [{'Service1', 'RpcName1}, ...]
get_proto_by_msg_name_as_fqbin(<<"Package.MsgName">>) -> "name"
get_proto_by_enum_name_as_fqbin(<<"Package.EnumName">>) -> "name"
get_protos_by_pkg_name_as_fqbin(<<"Package">>) -> ["name1", ...]
นอกจากนี้ยังมีฟังก์ชันข้อมูลเวอร์ชันบางส่วนด้วย:
gpb:version_as_string()
, gpb:version_as_list()
และ gpb:version_source()
GeneratedCode:version_as_string()
, GeneratedCode:version_as_list()
และGeneratedCode:version_source()
?gpb_version
(ใน gpb_version.hrl)?'GeneratedCode_gpb_version'
(ใน GeneratedCode.hrl)gpb ยังสามารถสร้างคำอธิบายตนเองของไฟล์โปรโตได้ คำอธิบายตนเองคือคำอธิบายของไฟล์โปรโต ซึ่งเข้ารหัสเป็นไบนารี่โดยใช้ descriptor.proto ที่มาพร้อมกับไลบรารีบัฟเฟอร์โปรโตคอลของ Google โปรดทราบว่าคำอธิบายตัวเองที่เข้ารหัสดังกล่าวจะไม่เป็นแบบไบต์ต่อไบต์เหมือนกับสิ่งที่คอมไพเลอร์บัฟเฟอร์โปรโตคอลของ Google จะสร้างสำหรับโปรโตเดียวกัน แต่ควรจะเทียบเท่ากันโดยคร่าว
ข้อความและฟิลด์ protobuf ที่เข้ารหัสอย่างผิดพลาดโดยทั่วไปจะทำให้ตัวถอดรหัสขัดข้อง ตัวอย่างของการเข้ารหัสที่ผิดพลาดดังกล่าวได้แก่:
แผนที่
Gpb สามารถสร้างตัวเข้ารหัส/ตัวถอดรหัสสำหรับแผนที่ได้
ตัวเลือก maps_unset_optional
สามารถใช้เพื่อระบุลักษณะการทำงานสำหรับฟิลด์ตัวเลือกที่ไม่มีอยู่: ไม่ว่าจะละเว้นจากแผนที่หรือมีอยู่ แต่มีค่า undefined
เช่นสำหรับบันทึก
การรายงานข้อผิดพลาดในไฟล์ .proto
Gpb ไม่ค่อยเก่งในการรายงานข้อผิดพลาด โดยเฉพาะข้อผิดพลาดในการอ้างอิง เช่น การอ้างอิงข้อความที่ไม่ได้กำหนดไว้ คุณอาจต้องการตรวจสอบกับ protoc
ก่อนว่าไฟล์ .proto นั้นถูกต้อง ก่อนที่จะส่งไปยัง gpb
สำหรับข้อมูลเกี่ยวกับวิธีการใช้ gpb กับ rebar3 ดูhttps://rebar3.org/docs/configuration/plugins/#protocol-buffers
ในเหล็กเส้นมีการรองรับ gpb ตั้งแต่เวอร์ชัน 2.6.0 ดูส่วนคอมไพเลอร์โปรโตของไฟล์ rebar.sample.config ที่ https://github.com/rebar/rebar/blob/master/rebar.config.sample
สำหรับเหล็กเส้นเวอร์ชันเก่า---ก่อน 2.6.0---ข้อความด้านล่างสรุปวิธีดำเนินการ:
วางไฟล์ .proto ไว้ในไดเร็กทอรีย่อย proto/
ไดเร็กทอรีย่อยใดๆ ที่ไม่ใช่ src/ ก็สามารถใช้ได้ เนื่องจาก rebar จะพยายามใช้คอมไพเลอร์ protobuf อื่นสำหรับ .proto ใดๆ ที่พบในไดเร็กทอรีย่อย src/ ต่อไปนี้เป็นบางบรรทัดสำหรับไฟล์ rebar.config
:
%% -*- erlang -*-
{pre_hooks,
[{compile, "mkdir -p include"}, %% ensure the include dir exists
{compile,
"/path/to/gpb/bin/protoc-erl -I`pwd`/proto"
"-o-erl src -o-hrl include `pwd`/proto/*.proto"
}]}.
{post_hooks,
[{clean,
"bash -c 'for f in proto/*.proto; "
"do "
" rm -f src/$(basename $f .proto).erl; "
" rm -f include/$(basename $f .proto).hrl; "
"done'"}
]}.
{erl_opts, [{i, "/path/to/gpb/include"}]}.
หมายเลขเวอร์ชัน gpb ถูกดึงมาจากแท็ก git ล่าสุดที่ตรงกับ NM โดยที่ N และ M เป็นจำนวนเต็ม เวอร์ชันนี้ถูกแทรกลงในไฟล์ gpb.app เช่นเดียวกับใน include/gpb_version.hrl เวอร์ชันเป็นผลจากคำสั่ง
git describe --always --tags --match '[0-9]*.[0-9]*'
ดังนั้น ในการสร้าง gpb เวอร์ชันใหม่ แหล่งที่มาเดียวจากการดึงข้อมูลเวอร์ชันนี้คือแท็ก git (หากคุณนำเข้า gpb ไปยังระบบควบคุมเวอร์ชันอื่นที่ไม่ใช่ git หรือใช้เครื่องมือสร้างอื่นที่ไม่ใช่ rebar คุณอาจต้องปรับ rebar.config และ src/gpb.app.src ตามนั้น โปรดดูส่วนด้านล่างเกี่ยวกับการสร้างภายนอก แผนผังงาน git สำหรับข้อมูลเกี่ยวกับการส่งออก gpb จาก git)
หมายเลขเวอร์ชันจากคำสั่ง git describe
ด้านบนจะมีลักษณะดังนี้
<x>.<y>.<z>
(บนมาสเตอร์บน Github)<x>.<y>.<z>-<n>-g<sha>
(บนสาขาหรือระหว่างการเปิดตัว) หมายเลขเวอร์ชันบนสาขาหลักของ gpb บน Github นั้นตั้งใจให้เป็นจำนวนเต็มที่มีจุดเท่านั้น เพื่อให้เข้ากันได้กับ reltool กล่าวอีกนัยหนึ่ง การพุชไปยังสาขาหลักของ Github แต่ละครั้งถือเป็นการเผยแพร่ และหมายเลขเวอร์ชันจะถูกกระแทก เพื่อให้แน่ใจว่าสิ่งนี้ มี git hook pre-push
และสคริปต์สองตัวคือ install-git-hooks
และ tag-next-minor-vsn
ในไดเร็กทอรีย่อย helpers ไฟล์ ChangeLog ไม่จำเป็นต้องแสดงถึงการเปลี่ยนแปลงเวอร์ชันเล็กๆ น้อยๆ ทั้งหมด แต่เป็นการอัปเดตที่สำคัญเท่านั้น
สถานที่ที่ต้องอัปเดตเมื่อสร้างเวอร์ชันใหม่:
กระบวนการสร้าง gpb คาดหวังแผนผังการทำงานคอมไพล์ (ไม่ตื้น) พร้อมด้วยแท็ก เพื่อให้ได้การกำหนดหมายเลขเวอร์ชันที่ถูกต้อง ดังที่อธิบายไว้ในส่วนการกำหนดหมายเลขเวอร์ชัน แต่ก็สามารถสร้างนอกคอมไพล์ได้เช่นกัน คุณมีสองทางเลือกในการดำเนินการดังกล่าว:
gpb.vsn
โดยมีเวอร์ชันอยู่ที่บรรทัดแรกhelpers/mk-versioned-archive
จากนั้นแตกไฟล์เก็บถาวรและสร้างภายในนั้น หากคุณสร้างไฟล์เก็บถาวรที่มีเวอร์ชันในแผนผังการทำงาน git เวอร์ชันจะถูกตั้งค่าโดยอัตโนมัติ ไม่เช่นนั้นคุณจะต้องระบุด้วยตนเอง เรียกใช้ mk-versioned-archive --help
เพื่อดูข้อมูลเกี่ยวกับตัวเลือกที่จะใช้
เมื่อดาวน์โหลดจาก Github ไฟล์เก็บถาวร gpb- <xyz> .tar.gz ได้ถูกสร้างขึ้นโดยใช้สคริปต์ mk-versioned-archive ดังนั้นจึงเป็นไปได้ที่จะแตกไฟล์และสร้างโดยตรง
หากคุณใช้ไฟล์ zip หรือไฟล์เก็บถาวร tar.gz ซอร์สโค้ด อัตโนมัติของ Github คุณจะต้องสร้างไฟล์ gpb.vsn
ตามที่อธิบายไว้ข้างต้น หรือสร้างไฟล์เก็บถาวรที่มีเวอร์ชันใหม่อีกครั้งโดยใช้สคริปต์ mk-versioned-archive
และ --override-version=<x>
ตัวเลือก (หรืออาจเป็นตัวเลือกหรือ --override-version-from-cwd-path
หากชื่อไดเร็กทอรีมีเวอร์ชันที่เหมาะสม)
ยินดีให้การสนับสนุน โดยเฉพาะอย่างยิ่งเป็นคำขอดึงหรือแพทช์ git หรือคำขอดึงข้อมูล git ต่อไปนี้คือคำแนะนำบางส่วน:
rebar clean; rebar eunit && rebar doc
ดู ChangeLog สำหรับรายละเอียด
ค่าเริ่มต้นสำหรับตัวเลือก maps_unset_optional
ได้เปลี่ยนเป็น omitted
จาก present_undefined
สิ่งนี้เกี่ยวข้องกับโค้ดที่สร้างด้วยตัวเลือกแผนที่ (-maps) เท่านั้น โปรเจ็กต์ที่ตั้งค่าตัวเลือกนี้ไว้อย่างชัดเจนจะไม่ได้รับผลกระทบ โปรเจ็กต์ที่ใช้ค่าเริ่มต้นเป็น present_undefined
จะต้องตั้งค่าตัวเลือกอย่างชัดเจนเพื่ออัปเกรดเป็น 4.0.0
สำหรับข้อกำหนดประเภท ค่าเริ่มต้นจะเปลี่ยนไปเพื่อสร้างเมื่อเป็นไปได้ ตัวเลือก {type_specs,false}
(-no_type) สามารถใช้เพื่อหลีกเลี่ยงการสร้างข้อมูลจำเพาะประเภท