prebuild.ml 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. open Json
  2. exception Prebuild_error of string
  3. type parsed_warning = {
  4. w_name : string;
  5. w_doc : string;
  6. w_parent : string option;
  7. w_generic : bool;
  8. w_enabled : bool;
  9. }
  10. type parsed_meta = {
  11. m_name : string;
  12. m_meta : string;
  13. m_doc : string;
  14. m_params : string list;
  15. m_platforms : string list;
  16. m_targets : string list;
  17. m_internal : bool;
  18. m_links : string list;
  19. }
  20. let as_string = function
  21. | JString s -> Some s
  22. | _ -> None
  23. let as_int = function
  24. | JInt i -> Some i
  25. | _ -> None
  26. let as_params = function
  27. | JArray s -> Some (List.map (function
  28. | JString s -> s
  29. | _ -> raise (Prebuild_error "parameter description should be a string")
  30. ) s)
  31. | _ -> None
  32. let as_platforms = function
  33. | JArray s -> Some (List.map (function
  34. | JString "cross" -> "Cross"
  35. | JString "js" -> "Js"
  36. | JString "lua" -> "Lua"
  37. | JString "neko" -> "Neko"
  38. | JString "flash" -> "Flash"
  39. | JString "php" -> "Php"
  40. | JString "cpp" -> "Cpp"
  41. | JString "jvm" -> "Jvm"
  42. | JString "python" -> "Python"
  43. | JString "hl" -> "Hl"
  44. | JString "eval" -> "Eval"
  45. | _ -> raise (Prebuild_error "invalid platform")
  46. ) s)
  47. | _ -> None
  48. let as_targets = function
  49. | JArray s -> Some (List.map (function
  50. | JString "TClass" -> "TClass"
  51. | JString "TClassField" -> "TClassField"
  52. | JString "TAbstract" -> "TAbstract"
  53. | JString "TAbstractField" -> "TAbstractField"
  54. | JString "TEnum" -> "TEnum"
  55. | JString "TTypedef" -> "TTypedef"
  56. | JString "TAnyField" -> "TAnyField"
  57. | JString "TExpr" -> "TExpr"
  58. | JString "TTypeParameter" -> "TTypeParameter"
  59. | _ -> raise (Prebuild_error "invalid metadata target")
  60. ) s)
  61. | _ -> None
  62. let as_bool = function
  63. | JBool b -> Some b
  64. | _ -> None
  65. let as_links = function
  66. | JArray s -> Some (List.map (function
  67. | JString s -> s
  68. | _ -> raise (Prebuild_error "link should be a string")
  69. ) s)
  70. | _ -> None
  71. let get_optional_field name map default fields =
  72. try
  73. let field = List.find (fun (n, _) -> n = name) fields in
  74. let value = map (snd field) in
  75. match value with
  76. | None -> raise (Prebuild_error ("field `" ^ name ^ "` has invalid data"))
  77. | Some v -> v
  78. with Not_found -> default
  79. let get_optional_field2 name map fields =
  80. try
  81. let field = List.find (fun (n, _) -> n = name) fields in
  82. let value = map (snd field) in
  83. match value with
  84. | None -> raise (Prebuild_error ("field `" ^ name ^ "` has invalid data"))
  85. | Some v -> Some v
  86. with Not_found ->
  87. None
  88. let get_field name map fields =
  89. let field = try List.find (fun (n, _) -> n = name) fields with Not_found -> raise (Prebuild_error ("no `" ^ name ^ "` field")) in
  90. let value = map (snd field) in
  91. match value with
  92. | None -> raise (Prebuild_error ("field `" ^ name ^ "` has invalid data"))
  93. | Some v -> v
  94. let parse_define json =
  95. let fields = match json with
  96. | JObject fl -> fl
  97. | _ -> raise (Prebuild_error "not an object")
  98. in
  99. (* name *) get_field "name" as_string fields,
  100. (* define *) get_field "define" as_string fields,
  101. (* doc *) get_field "doc" as_string fields,
  102. (* params *) get_optional_field "params" as_params [] fields,
  103. (* platforms *) get_optional_field "platforms" as_platforms [] fields,
  104. (* links *) get_optional_field "links" as_links [] fields,
  105. (* deprecated *) get_optional_field2 "deprecated" as_string fields
  106. let parse_meta json =
  107. let fields = match json with
  108. | JObject fl -> fl
  109. | _ -> raise (Prebuild_error "not an object")
  110. in
  111. {
  112. m_name = get_field "name" as_string fields;
  113. m_meta = get_field "metadata" as_string fields;
  114. m_doc = get_field "doc" as_string fields;
  115. m_params = get_optional_field "params" as_params [] fields;
  116. m_platforms = get_optional_field "platforms" as_platforms [] fields;
  117. m_targets = get_optional_field "targets" as_targets [] fields;
  118. m_internal = get_optional_field "internal" as_bool false fields;
  119. m_links = get_optional_field "links" as_links [] fields
  120. }
  121. let parse_warning json =
  122. let fields = match json with
  123. | JObject fl -> fl
  124. | _ -> raise (Prebuild_error "not an object")
  125. in
  126. {
  127. w_name = get_field "name" as_string fields;
  128. w_doc = get_field "doc" as_string fields;
  129. w_parent = get_optional_field2 "parent" as_string fields;
  130. w_generic = get_optional_field "generic" as_bool false fields;
  131. w_enabled = get_optional_field "enabled" as_bool true fields;
  132. }
  133. let parse_file_array path map =
  134. let file = open_in path in
  135. let data = Std.input_all file in
  136. let open Json.Reader in
  137. let lexbuf = Sedlexing.Utf8.from_string data in
  138. let json = read_json lexbuf in
  139. match json with
  140. | JArray s -> List.map map s
  141. | _ -> raise (Prebuild_error "not an array")
  142. let s_escape ?(hex=true) s =
  143. let b = Buffer.create (String.length s) in
  144. for i = 0 to (String.length s) - 1 do
  145. match s.[i] with
  146. | '\n' -> Buffer.add_string b "\\n"
  147. | '\t' -> Buffer.add_string b "\\t"
  148. | '\r' -> Buffer.add_string b "\\r"
  149. | '"' -> Buffer.add_string b "\\\""
  150. | '\\' -> Buffer.add_string b "\\\\"
  151. | c when int_of_char c < 32 && hex -> Buffer.add_string b (Printf.sprintf "\\x%.2X" (int_of_char c))
  152. | c -> Buffer.add_char b c
  153. done;
  154. Buffer.contents b
  155. let gen_platforms = function
  156. | [] -> []
  157. | platforms -> ["Platforms [" ^ (String.concat ";" platforms) ^ "]"]
  158. let gen_params = List.map (function param -> "HasParam \"" ^ param ^ "\"" )
  159. let gen_links = List.map (function link -> "Link \"" ^ link ^ "\"" )
  160. let gen_define_type defines =
  161. String.concat "\n" (List.map (function (name, _, _, _, _, _, _) -> "\t| " ^ name) defines)
  162. let gen_option f = function
  163. | None -> "None"
  164. | Some x -> Printf.sprintf "Some(%s)" (f x)
  165. let gen_define_info defines =
  166. let deprecations = DynArray.create() in
  167. let define_str = List.map (function
  168. (name, define, doc, params, platforms, links, deprecated) ->
  169. let platforms_str = gen_platforms platforms in
  170. let params_str = gen_params params in
  171. let links_str = gen_links links in
  172. let define = String.concat "_" (ExtString.String.nsplit define "-") in
  173. let deprecated = match deprecated with
  174. | None ->
  175. []
  176. | Some x ->
  177. let quoted = Printf.sprintf "%S" x in
  178. DynArray.add deprecations (Printf.sprintf "\t(%S,%S)" define x);
  179. [Printf.sprintf "Deprecated(%s)" quoted]
  180. in
  181. "\t| " ^ name ^ " -> \"" ^ define ^ "\",(" ^ (Printf.sprintf "%S" doc) ^ ",[" ^ (String.concat "; " (platforms_str @ params_str @ links_str @ deprecated)) ^ "])"
  182. ) defines in
  183. String.concat "\n" define_str,String.concat ";\n" (DynArray.to_list deprecations)
  184. let gen_meta_type metas =
  185. String.concat "\n" (List.map (function
  186. | {m_name = "InlineConstructorArgument"} -> "\t| InlineConstructorArgument of int * int"
  187. | {m_name = name} -> "\t| " ^ name
  188. ) metas)
  189. let gen_meta_info metas =
  190. let meta_str = List.map (function meta ->
  191. let platforms_str = gen_platforms meta.m_platforms in
  192. let params_str = gen_params meta.m_params in
  193. let targets_str = (match meta.m_targets with
  194. | [] -> []
  195. | targets -> ["UsedOn [" ^ (String.concat ";" targets) ^ "]"]
  196. ) in
  197. let internal_str = if meta.m_internal then ["UsedInternally"] else [] in
  198. let links_str = gen_links meta.m_links in
  199. let name = (match meta.m_name with
  200. (* this is a hacky, I know *)
  201. | "InlineConstructorArgument" -> "InlineConstructorArgument _"
  202. | _ -> meta.m_name
  203. ) in
  204. "\t| " ^ name ^ " -> \"" ^ meta.m_meta ^ "\",(" ^ (Printf.sprintf "%S" meta.m_doc) ^ ",[" ^ (String.concat "; " (platforms_str @ params_str @ targets_str @ internal_str @ links_str)) ^ "])"
  205. ) metas in
  206. String.concat "\n" meta_str
  207. let gen_warning_type warnings =
  208. let warning_str = List.map (function
  209. w ->
  210. Printf.sprintf "\t| %s" w.w_name
  211. ) warnings in
  212. String.concat "\n" warning_str
  213. let gen_warning_parse warnings =
  214. let warning_str = List.map (function
  215. w ->
  216. Printf.sprintf "\t| \"%s\" -> %s" w.w_name w.w_name
  217. ) warnings in
  218. let warning_str = warning_str @ ["\t| _ -> raise Exit"] in
  219. String.concat "\n" warning_str
  220. let gen_warning_obj warnings =
  221. let warning_str = List.map (fun w ->
  222. let w_parent = match w.w_parent with
  223. | None -> if w.w_name = "WAll" then "None" else "Some WAll"
  224. | Some w -> Printf.sprintf "Some %s" w
  225. in
  226. Printf.sprintf "\t| %s -> {w_name = \"%s\"; w_doc = \"%s\"; w_generic = %b; w_parent = %s}" w.w_name w.w_name (s_escape w.w_doc) w.w_generic w_parent
  227. ) warnings in
  228. String.concat "\n" warning_str
  229. let gen_disabled_warnings warnings =
  230. let warning_str = ExtList.List.filter_map (fun w ->
  231. if w.w_enabled then
  232. None
  233. else
  234. Some w.w_name
  235. ) warnings in
  236. String.concat ";" warning_str
  237. let autogen_header = "(* This file is auto-generated using prebuild from files in src-json *)
  238. (* Do not edit manually! *)
  239. "
  240. let define_header = autogen_header ^ "
  241. open Globals
  242. type define_parameter =
  243. | HasParam of string
  244. | Platforms of platform list
  245. | Link of string
  246. | Deprecated of string
  247. "
  248. let meta_header = autogen_header ^ "
  249. open Globals
  250. type meta_usage =
  251. | TClass
  252. | TClassField
  253. | TAbstract
  254. | TAbstractField
  255. | TEnum
  256. | TTypedef
  257. | TAnyField
  258. | TExpr
  259. | TTypeParameter
  260. | TVariable
  261. let parse_meta_usage = function
  262. | \"TClass\" -> TClass
  263. | \"TClassField\" -> TClassField
  264. | \"TAbstract\" -> TAbstract
  265. | \"TAbstractField\" -> TAbstractField
  266. | \"TEnum\" -> TEnum
  267. | \"TTypedef\" -> TTypedef
  268. | \"TAnyField\" -> TAnyField
  269. | \"TExpr\" -> TExpr
  270. | \"TTypeParameter\" -> TTypeParameter
  271. | \"TVariable\" -> TVariable
  272. | t -> raise (failwith (\"invalid metadata target \" ^ t))
  273. let print_meta_usage = function
  274. | TClass -> \"TClass\"
  275. | TClassField -> \"TClassField\"
  276. | TAbstract -> \"TAbstract\"
  277. | TAbstractField -> \"TAbstractField\"
  278. | TEnum -> \"TEnum\"
  279. | TTypedef -> \"TTypedef\"
  280. | TAnyField -> \"TAnyField\"
  281. | TExpr -> \"TExpr\"
  282. | TTypeParameter -> \"TTypeParameter\"
  283. | TVariable -> \"TVariable\"
  284. type meta_parameter =
  285. | HasParam of string
  286. | Platforms of platform list
  287. | UsedOn of meta_usage list
  288. | UsedInternally
  289. | Link of string
  290. "
  291. ;;
  292. match Array.to_list (Sys.argv) with
  293. | [_; "define"; define_path]->
  294. let defines = parse_file_array define_path parse_define in
  295. Printf.printf "%s" define_header;
  296. Printf.printf "type strict_defined =\n";
  297. Printf.printf "%s" (gen_define_type defines);
  298. Printf.printf "\n\t| Last\n\t| Custom of string\n\n";
  299. let infos,deprecations = gen_define_info defines in
  300. Printf.printf "let infos = function\n";
  301. Printf.printf "%s" infos;
  302. Printf.printf "\n\t| Last -> die \"\" __LOC__\n\t| Custom s -> s,(\"\",[])\n";
  303. Printf.printf "\nlet deprecated_defines = [\n%s\n]\n" deprecations;
  304. | [_; "meta"; meta_path]->
  305. let metas = parse_file_array meta_path parse_meta in
  306. Printf.printf "%s" meta_header;
  307. Printf.printf "type strict_meta =\n";
  308. Printf.printf "%s" (gen_meta_type metas);
  309. Printf.printf "\n\t| Last\n\t| Dollar of string\n\t| Custom of string\n\n";
  310. Printf.printf "let get_info = function\n";
  311. Printf.printf "%s" (gen_meta_info metas);
  312. Printf.printf "\n\t| Last -> die \"\" __LOC__\n\t| Dollar s -> \"$\" ^ s,(\"\",[])\n\t| Custom s -> s,(\"\",[])\n"
  313. | [_; "warning"; warning_path]->
  314. let warnings = parse_file_array warning_path parse_warning in
  315. print_endline "type warning =";
  316. print_endline (gen_warning_type warnings);
  317. print_endline "";
  318. print_endline "type warning_obj = {";
  319. print_endline "\tw_name : string;";
  320. print_endline "\tw_doc : string;";
  321. print_endline "\tw_generic : bool;";
  322. print_endline "\tw_parent : warning option;";
  323. print_endline "}";
  324. print_endline "";
  325. print_endline "let warning_obj = function";
  326. print_endline (gen_warning_obj warnings);
  327. print_endline ";;";
  328. print_endline "let disabled_warnings = [";
  329. print_endline (gen_disabled_warnings warnings);
  330. print_endline "];;";
  331. print_endline "";
  332. print_endline "let from_string = function";
  333. print_endline (gen_warning_parse warnings);
  334. | [_; "libparams"; os] ->
  335. Printf.printf "(";
  336. (begin match Sys.getenv_opt "LIB_PARAMS" with
  337. | Some params ->
  338. Printf.printf "%s" params;
  339. | None ->
  340. if Sys.win32 then
  341. Printf.printf "-cclib -lpcre2-8 -cclib -lz -cclib -lcrypt32 -cclib -lmbedtls -cclib -lmbedcrypto -cclib -lmbedx509"
  342. else
  343. if Option.is_some (Sys.getenv_opt "STATICLINK") && os <> "macosx" then
  344. Printf.printf "-cclib \"-Wl,-Bstatic -lpcre2-8 -lz -lmbedtls -lmbedx509 -lmbedcrypto -Wl,-Bdynamic \""
  345. else
  346. Printf.printf "-cclib -lpcre2-8 -cclib -lz -cclib -lmbedtls -cclib -lmbedx509 -cclib -lmbedcrypto";
  347. end);
  348. if os = "macosx" then Printf.printf " -cclib \"-framework Security -framework CoreFoundation\"";
  349. Printf.printf ")";
  350. | [_ ;"version";] ->
  351. begin match Sys.getenv_opt "ADD_REVISION" with
  352. | Some "0" | Some "" | None ->
  353. print_endline "let version_extra = None"
  354. | _ ->
  355. let branch = Stdlib.input_line (Unix.open_process_in "git rev-parse --abbrev-ref HEAD") in
  356. let sha = Stdlib.input_line (Unix.open_process_in "git rev-parse --short HEAD") in
  357. Printf.printf "let version_extra = Some (\"git build %s\",\"%s\")" branch sha
  358. end
  359. | args ->
  360. print_endline (String.concat ", " args)