Browse Source

Hxb writer config (#11507)

* start on writer config

* functorize

* add Compiler.setHxbWriterConfiguration

* rename

* add Compiler.getHxbWriterConfiguration

* document

* substitute $target when we actually need it

* fix my favorite test

* file

* add generateDocumentation

* don't forget the writer

* (temporarily?) read until EOT immediately

see #11512
Simon Krajewski 1 year ago
parent
commit
3280f2f72a

+ 3 - 3
src/compiler/args.ml

@@ -278,9 +278,9 @@ let parse_args com =
 		("Services",["--json"],[],Arg.String (fun file ->
 			actx.json_out <- Some file
 		),"<file>","generate JSON types description");
-		("Services",["--hxb"],[], Arg.String (fun dir ->
-			actx.hxb_out <- Some dir;
-		),"<directory>", "generate haxe binary representation in target directory");
+		("Services",["--hxb"],[], Arg.String (fun file ->
+			actx.hxb_out <- Some file;
+		),"<file>", "generate haxe binary representation to target archive");
 		("Optimization",["--no-output"],[], Arg.Unit (fun() -> actx.no_output <- true),"","compiles but does not generate any file");
 		("Debug",["--times"],[], Arg.Unit (fun() -> Timer.measure_times := true),"","measure compilation times");
 		("Optimization",["--no-inline"],[],Arg.Unit (fun () ->

+ 2 - 2
src/compiler/compilationCache.ml

@@ -69,12 +69,12 @@ class context_cache (index : int) (sign : Digest.t) = object(self)
 	method find_module_extra path =
 		try (Hashtbl.find modules path).m_extra with Not_found -> (Hashtbl.find binary_cache path).mc_extra
 
-	method cache_module warn anon_identification hxb_writer_stats path m =
+	method cache_module config warn anon_identification hxb_writer_stats path m =
 		match m.m_extra.m_kind with
 		| MImport ->
 			Hashtbl.add modules m.m_path m
 		| _ ->
-			let writer = HxbWriter.create warn anon_identification hxb_writer_stats in
+			let writer = HxbWriter.create config warn anon_identification hxb_writer_stats in
 			HxbWriter.write_module writer m;
 			let chunks = HxbWriter.get_chunks writer in
 			Hashtbl.replace binary_cache path {

+ 11 - 1
src/compiler/compiler.ml

@@ -369,6 +369,12 @@ let compile ctx actx callbacks =
 	callbacks.after_target_init ctx;
 	let t = Timer.timer ["init"] in
 	List.iter (fun f -> f()) (List.rev (actx.pre_compilation));
+	begin match actx.hxb_out with
+		| None ->
+			()
+		| Some file ->
+			com.hxb_writer_config <- HxbWriterConfig.process_argument file
+	end;
 	t();
 	enter_stage com CInitialized;
 	ServerMessage.compiler_stage com;
@@ -382,7 +388,11 @@ let compile ctx actx callbacks =
 		let is_compilation = is_compilation com in
 		com.callbacks#add_after_save (fun () ->
 			callbacks.after_save ctx;
-			if is_compilation then Generate.check_hxb_output ctx actx;
+			if is_compilation then match com.hxb_writer_config with
+				| Some config ->
+					Generate.check_hxb_output ctx config;
+				| None ->
+					()
 		);
 		if is_diagnostics com then
 			filter ctx tctx (fun () -> DisplayProcessing.handle_display_after_finalization ctx tctx display_file_dot_path)

+ 26 - 17
src/compiler/generate.ml

@@ -21,7 +21,7 @@ let check_auxiliary_output com actx =
 			Genjson.generate com.types file
 	end
 
-let export_hxb com cc platform zip m =
+let export_hxb com config cc platform zip m =
 	let open HxbData in
 	match m.m_extra.m_kind with
 		| MCode | MMacro | MFake | MExtern -> begin
@@ -42,7 +42,7 @@ let export_hxb com cc platform zip m =
 			with Not_found ->
 				let anon_identification = new tanon_identification in
 				let warn w s p = com.Common.warning w com.warning_options s p in
-				let writer = HxbWriter.create warn anon_identification com.hxb_writer_stats in
+				let writer = HxbWriter.create config warn anon_identification com.hxb_writer_stats in
 				HxbWriter.write_module writer m;
 				let out = IO.output_string () in
 				HxbWriter.export writer out;
@@ -51,37 +51,46 @@ let export_hxb com cc platform zip m =
 	| _ ->
 		()
 
-let check_hxb_output ctx actx =
+let check_hxb_output ctx config =
+	let open HxbWriterConfig in
 	let com = ctx.com in
-	let try_write path =
+	let match_path_list l sl_path =
+		List.exists (fun sl -> Ast.match_path true sl_path sl) l
+	in
+	let try_write () =
+		let path = config.HxbWriterConfig.archive_path in
+		let path = Str.global_replace (Str.regexp "\\$target") (platform_name ctx.com.platform) path in
 		let t = Timer.timer ["generate";"hxb"] in
 		Path.mkdir_from_path path;
 		let zip = new Zip_output.zip_output path 6 in
-		let export com =
+		let export com config =
 			let cc = CommonCache.get_cache com in
 			let target = Common.platform_name_macro com in
 			List.iter (fun m ->
 				let t = Timer.timer ["generate";"hxb";s_type_path m.m_path] in
-				Std.finally t (export_hxb com cc target zip) m
+				let sl_path = fst m.m_path @ [snd m.m_path] in
+				if not (match_path_list config.exclude sl_path) || match_path_list config.include' sl_path then
+					Std.finally t (export_hxb com config cc target zip) m
 			) com.modules;
 		in
 		Std.finally (fun () ->
 			zip#close;
 			t()
 		) (fun () ->
-			export com;
-			Option.may export (com.get_macros());
+			if  config.target_config.generate then
+				export com config.target_config;
+			begin match com.get_macros() with
+				| Some mcom when config.macro_config.generate ->
+					export mcom config.macro_config
+				| _ ->
+					()
+			end;
 		) ()
 	in
-	begin match actx.hxb_out with
-		| None ->
-			()
-		| Some path ->
-			try
-				try_write path
-			with Sys_error s ->
-				error ctx (Printf.sprintf "Could not write to %s: %s" path s) null_pos
-	end
+	try
+		try_write ()
+	with Sys_error s ->
+		CompilationContext.error ctx (Printf.sprintf "Could not write to %s: %s" config.archive_path s) null_pos
 
 let parse_swf_header ctx h = match ExtString.String.nsplit h ":" with
 		| [width; height; fps] ->

+ 19 - 12
src/compiler/hxb/hxbWriter.ml

@@ -511,6 +511,7 @@ let create_field_writer_context pos_writer = {
 }
 
 type hxb_writer = {
+	config : HxbWriterConfig.writer_target_config;
 	warn : Warning.warning -> string -> Globals.pos -> unit;
 	anon_id : Type.t Tanon_identification.tanon_identification;
 	stats : hxb_writer_stats;
@@ -601,13 +602,18 @@ module HxbWriter = struct
 		Chunk.write_string writer.chunk mname;
 		Chunk.write_string writer.chunk tname
 
-	let write_documentation writer (doc : doc_block) =
-		Chunk.write_option writer.chunk doc.doc_own (fun s ->
-			Chunk.write_uleb128 writer.chunk (StringPool.get_or_add writer.docs s)
-		);
-		Chunk.write_list writer.chunk doc.doc_inherited (fun s ->
-			Chunk.write_uleb128 writer.chunk (StringPool.get_or_add writer.docs s)
-		)
+	let maybe_write_documentation writer (doc : doc_block option) =
+		match doc with
+		| Some doc when writer.config.generate_docs ->
+			Chunk.write_u8 writer.chunk 1;
+			Chunk.write_option writer.chunk doc.doc_own (fun s ->
+				Chunk.write_uleb128 writer.chunk (StringPool.get_or_add writer.docs s)
+			);
+			Chunk.write_list writer.chunk doc.doc_inherited (fun s ->
+				Chunk.write_uleb128 writer.chunk (StringPool.get_or_add writer.docs s)
+			)
+		| _ ->
+			Chunk.write_u8 writer.chunk 0
 
 	let write_pos writer (p : pos) =
 		Chunk.write_string writer.chunk p.pfile;
@@ -753,7 +759,7 @@ module HxbWriter = struct
 
 	and write_cfield writer cff =
 		write_placed_name writer cff.cff_name;
-		Chunk.write_option writer.chunk cff.cff_doc (write_documentation writer);
+		maybe_write_documentation writer cff.cff_doc;
 		write_pos writer cff.cff_pos;
 		write_metadata writer cff.cff_meta;
 		Chunk.write_list writer.chunk cff.cff_access (write_placed_access writer);
@@ -1829,7 +1835,7 @@ module HxbWriter = struct
 		let restore = start_temporary_chunk writer 512 in
 		write_type_instance writer cf.cf_type;
 		Chunk.write_uleb128 writer.chunk cf.cf_flags;
-		Chunk.write_option writer.chunk cf.cf_doc (write_documentation writer);
+		maybe_write_documentation writer cf.cf_doc;
 		write_metadata writer cf.cf_meta;
 		write_field_kind writer cf.cf_kind;
 		let expr_chunk = match cf.cf_expr with
@@ -1876,7 +1882,7 @@ module HxbWriter = struct
 
 	let write_common_module_type writer (infos : tinfos) : unit =
 		Chunk.write_bool writer.chunk infos.mt_private;
-		Chunk.write_option writer.chunk infos.mt_doc (write_documentation writer);
+		maybe_write_documentation writer infos.mt_doc;
 		write_metadata writer infos.mt_meta;
 		write_type_parameters_data writer infos.mt_params;
 		Chunk.write_list writer.chunk infos.mt_using (fun (c,p) ->
@@ -2141,7 +2147,7 @@ module HxbWriter = struct
 					let t_bytes = restore (fun new_chunk -> Chunk.get_bytes new_chunk) in
 					commit_field_type_parameters writer ef.ef_params;
 					Chunk.write_bytes writer.chunk t_bytes;
-					Chunk.write_option writer.chunk ef.ef_doc (write_documentation writer);
+					maybe_write_documentation writer ef.ef_doc;
 					write_metadata writer ef.ef_meta;
 					close();
 				);
@@ -2281,9 +2287,10 @@ module HxbWriter = struct
 		l
 end
 
-let create warn anon_id stats =
+let create config warn anon_id stats =
 	let cp = StringPool.create () in
 	{
+		config;
 		warn;
 		anon_id;
 		stats;

+ 119 - 0
src/compiler/hxb/hxbWriterConfig.ml

@@ -0,0 +1,119 @@
+open Globals
+open Json
+open Json.Reader
+
+type writer_target_config = {
+	mutable generate : bool;
+	mutable exclude : string list list;
+	mutable include' : string list list;
+	mutable hxb_version : int;
+	mutable generate_docs : bool;
+}
+
+type t = {
+	mutable archive_path : string;
+	target_config : writer_target_config;
+	macro_config : writer_target_config;
+}
+
+let create_target_config () = {
+	generate = true;
+	exclude = [];
+	include'= [];
+	hxb_version = HxbData.hxb_version;
+	generate_docs = true;
+}
+
+let create () = {
+	archive_path = "";
+	target_config = create_target_config ();
+	macro_config = create_target_config ()
+}
+let error s =
+	Error.raise_typing_error s null_pos
+
+module WriterConfigReader (API : DataReaderApi.DataReaderApi) = struct
+	let read_target_config config fl =
+		List.iter (fun (s,data) -> match s with
+			| "generate" ->
+				config.generate <- API.read_bool data;
+			| "exclude" ->
+				API.read_optional data (fun data ->
+					let l = API.read_array data in
+					config.exclude <- List.map (fun data -> ExtString.String.nsplit (API.read_string data) ".") l
+				)
+			| "include" ->
+				API.read_optional data (fun data ->
+					let l = API.read_array data in
+					config.include'<- List.map (fun data -> ExtString.String.nsplit (API.read_string data) ".") l
+				)
+			| "hxbVersion" ->
+				config.hxb_version <- API.read_int data
+			| "generateDocumentation" ->
+				config.generate_docs <- API.read_bool data
+			| s ->
+				error (Printf.sprintf "Unknown key for target config: %s" s)
+		) fl
+
+	let read_writer_config config data =
+		let read data =
+			let fl = API.read_object data in
+			List.iter (fun (s,data) ->
+				match s with
+				| "archivePath" ->
+					config.archive_path <- API.read_string data;
+				| "targetConfig" ->
+					API.read_optional data (fun data -> read_target_config config.target_config (API.read_object data))
+				| "macroConfig" ->
+					API.read_optional data (fun data -> read_target_config config.macro_config (API.read_object data))
+				| s ->
+					error (Printf.sprintf "Unknown key for writer config: %s" s)
+			) fl
+		in
+		API.read_optional data read
+end
+
+module WriterConfigReaderJson = WriterConfigReader(JsonDataApi.JsonReaderApi)
+
+module WriterConfigWriter (API : DataWriterApi.DataWriterApi) = struct
+	let write_target_config config =
+		API.write_object [
+			"generate",API.write_bool config.generate;
+			"exclude",API.write_array (List.map (fun sl -> API.write_string (String.concat "." sl)) config.exclude);
+			"include",API.write_array (List.map (fun sl -> API.write_string (String.concat "." sl)) config.include');
+			"hxbVersion",API.write_int config.hxb_version;
+			"generateDocumentation",API.write_bool config.generate_docs;
+		]
+
+	let write_writer_config config =
+		API.write_object [
+			"archivePath",API.write_string config.archive_path;
+			"targetConfig",write_target_config config.target_config;
+			"macroConfig",write_target_config config.macro_config;
+		]
+end
+
+let process_json config json =
+	WriterConfigReaderJson.read_writer_config config json
+
+let parse config input =
+	let lexbuf = Sedlexing.Utf8.from_string input in
+	let json = read_json lexbuf in
+	process_json config json
+
+let process_argument file =
+	let config = create () in
+	begin match Path.file_extension file with
+		| "json" ->
+			let file = try
+				open_in file
+			with exc ->
+				error (Printf.sprintf "Could not open file %s: %s" file (Printexc.to_string exc))
+			in
+			let data = Std.input_all file in
+			close_in file;
+			parse config data;
+		| _ ->
+			config.archive_path <- file;
+	end;
+	Some config

+ 2 - 0
src/context/common.ml

@@ -421,6 +421,7 @@ type context = {
 	memory_marker : float array;
 	hxb_reader_stats : HxbReader.hxb_reader_stats;
 	hxb_writer_stats : HxbWriter.hxb_writer_stats;
+	mutable hxb_writer_config : HxbWriterConfig.t option;
 }
 
 let enter_stage com stage =
@@ -883,6 +884,7 @@ let create compilation_step cs version args display_mode =
 		is_macro_context = false;
 		hxb_reader_stats = HxbReader.create_hxb_reader_stats ();
 		hxb_writer_stats = HxbWriter.create_hxb_writer_stats ();
+		hxb_writer_config = None;
 	} in
 	com
 

+ 7 - 1
src/context/commonCache.ml

@@ -85,11 +85,17 @@ let rec cache_context cs com =
 	let cc = get_cache com in
 	let sign = Define.get_signature com.defines in
 	let anon_identification = new Tanon_identification.tanon_identification in
+	let config = match com.hxb_writer_config with
+		| None ->
+			HxbWriterConfig.create_target_config ()
+		| Some config ->
+			if com.is_macro_context then config.macro_config else config.target_config
+	in
 	let cache_module m =
 		(* If we have a signature mismatch, look-up cache for module. Physical equality check is fine as a heueristic. *)
 		let cc = if m.m_extra.m_sign = sign then cc else cs#get_context m.m_extra.m_sign in
 		let warn w s p = com.warning w com.warning_options s p in
-		cc#cache_module warn anon_identification com.hxb_writer_stats m.m_path m;
+		cc#cache_module config warn anon_identification com.hxb_writer_stats m.m_path m;
 	in
 	List.iter cache_module com.modules;
 	begin match com.get_macros() with

+ 17 - 0
src/core/data/dataReaderApi.ml

@@ -0,0 +1,17 @@
+module type DataReaderApi = sig
+	type data
+
+	val read_optional : data -> (data -> unit) -> unit
+
+	val read_object : data -> (string * data) list
+
+	val read_array : data -> data list
+
+	val read_string : data -> string
+
+	val read_bool : data -> bool
+
+	val read_int : data -> int
+
+	val data_to_string : data -> string
+end

+ 15 - 0
src/core/data/dataWriterApi.ml

@@ -0,0 +1,15 @@
+module type DataWriterApi = sig
+	type data
+
+	val write_optional : data option -> data
+
+	val write_object : (string * data) list -> data
+
+	val write_array : data list -> data
+
+	val write_string : string -> data
+
+	val write_bool : bool -> data
+
+	val write_int : int -> data
+end

+ 48 - 0
src/core/data/jsonDataApi.ml

@@ -0,0 +1,48 @@
+open Json
+
+let error s =
+	(* TODO: should this raise something else? *)
+	Error.raise_typing_error s Globals.null_pos
+
+module JsonReaderApi = struct
+	type data = Json.t
+
+	let read_optional json f = match json with
+		| JNull ->
+			()
+		| _ ->
+			f json
+
+	let read_object json = match json with
+		| JObject fl ->
+			fl
+		| _ ->
+			error (Printf.sprintf "Expected JObject, found %s" (string_of_json json))
+
+	let read_array json = match json with
+		| JArray l ->
+			l
+		| _ ->
+			error (Printf.sprintf "Expected JArray, found %s" (string_of_json json))
+
+	let read_string json = match json with
+		| JString s ->
+			s
+		| _ ->
+			error (Printf.sprintf "Expected JString, found %s" (string_of_json json))
+
+	let read_int json = match json with
+		| JInt i ->
+			i
+		| _ ->
+			error (Printf.sprintf "Expected JInt, found %s" (string_of_json json))
+
+	let read_bool json = match json with
+		| JBool b ->
+			b
+		| _ ->
+			error (Printf.sprintf "Expected JBool, found %s" (string_of_json json))
+
+	let data_to_string json =
+		string_of_json json
+end

+ 61 - 0
src/macro/eval/evalDataApi.ml

@@ -0,0 +1,61 @@
+open EvalValue
+open EvalContext
+
+module EvalReaderApi = struct
+	open EvalDecode
+
+	type data = value
+
+	let read_optional v f = match v with
+		| VNull ->
+			()
+		| _ ->
+			f v
+
+	let read_object v =
+		List.map (fun (i,v) ->
+			EvalHash.rev_hash i,v
+		) (object_fields (decode_object v))
+
+	let read_array v =
+		EvalArray.to_list (decode_varray v)
+
+	let read_string v =
+		decode_string v
+
+	let read_int v =
+		decode_int v
+
+	let read_bool v =
+		decode_bool v
+
+	let data_to_string v =
+		(EvalPrinting.s_value 0 v).sstring
+end
+
+module EvalWriterApi = struct
+	open EvalEncode
+
+	type data = value
+
+	let write_optional vo = match vo with
+		| None -> vnull
+		| Some v -> v
+
+	let write_object fl =
+		encode_obj (List.map (fun (s,v) ->
+			EvalHash.hash s,v
+		) fl)
+
+	let write_array vl =
+		encode_array vl
+
+	let write_string s =
+		encode_string s
+
+	let write_bool b =
+		vbool b
+
+	let write_int i =
+		vint i
+end

+ 9 - 0
src/macro/macroApi.ml

@@ -70,6 +70,8 @@ type 'value compiler_api = {
 	with_imports : 'a . import list -> placed_name list list -> (unit -> 'a) -> 'a;
 	with_options : 'a . compiler_options -> (unit -> 'a) -> 'a;
 	exc_string : 'a . string -> 'a;
+	get_hxb_writer_config : unit -> 'value;
+	set_hxb_writer_config : 'value -> unit;
 }
 
 
@@ -2405,5 +2407,12 @@ let macro_api ccom get_api =
 				vbool false
 			end
 		);
+		"get_hxb_writer_config", vfun0 (fun () ->
+			(get_api()).get_hxb_writer_config ()
+		);
+		"set_hxb_writer_config", vfun1 (fun v ->
+			(get_api()).set_hxb_writer_config v;
+			vnull
+		)
 	]
 end

+ 26 - 0
src/typing/macroContext.ml

@@ -34,6 +34,10 @@ module Interp = struct
 	include BuiltApi
 end
 
+
+module HxbWriterConfigReaderEval = HxbWriterConfig.WriterConfigReader(EvalDataApi.EvalReaderApi)
+module HxbWriterConfigWriterEval = HxbWriterConfig.WriterConfigWriter(EvalDataApi.EvalWriterApi)
+
 let macro_interp_cache = ref None
 
 let safe_decode com v expected t p f =
@@ -305,6 +309,28 @@ let make_macro_com_api com mcom p =
 			com.warning ~depth w [] msg p
 		);
 		exc_string = Interp.exc_string;
+		get_hxb_writer_config = (fun () ->
+			match com.hxb_writer_config with
+			| Some config ->
+				HxbWriterConfigWriterEval.write_writer_config config
+			| None ->
+				VNull
+		);
+		set_hxb_writer_config = (fun v ->
+			if v == VNull then
+				com.hxb_writer_config <- None
+			else begin
+				let config = match com.hxb_writer_config with
+					| Some config ->
+						config
+					| None ->
+						let config = HxbWriterConfig.create () in
+						com.hxb_writer_config <- Some config;
+						config
+				in
+				HxbWriterConfigReaderEval.read_writer_config config v
+			end
+		);
 	}
 
 let make_macro_api ctx mctx p =

+ 3 - 6
src/typing/typeloadModule.ml

@@ -818,12 +818,9 @@ let rec load_hxb_module ctx path p =
 			let api = (new hxb_reader_api_typeload ctx load_module' p :> HxbReaderApi.hxb_reader_api) in
 			let reader = new HxbReader.hxb_reader path ctx.com.hxb_reader_stats in
 			let read = reader#read api bytes in
-			let m = read MTF in
-			delay ctx PBuildClass (fun () ->
-				ignore(read EOT);
-				delay ctx PConnectField (fun () ->
-					ignore(read EOM);
-				);
+			let m = read EOT in
+			delay ctx PConnectField (fun () ->
+				ignore(read EOM);
 			);
 			m
 		with e ->

+ 51 - 0
std/haxe/hxb/WriterConfig.hx

@@ -0,0 +1,51 @@
+package haxe.hxb;
+
+typedef WriterTargetConfig = {
+	/**
+		If `false`, this target is ignored by the writer.
+	**/
+	var ?generate:Null<Bool>;
+
+	/**
+		Dot paths of modules or packages to be exluded from the archive.
+	**/
+	var ?exclude:Null<Array<String>>;
+
+	/**
+		Dot paths of modules or packages to be included in the archive. This takes priority
+		over exclude. By default, all modules that aren't explicitly excluded are
+		included.
+	**/
+	var ?include:Null<Array<String>>;
+
+	/**
+		The hxb version to target. By default, the version of the Haxe compiler itself
+		is targeted. See https://github.com/HaxeFoundation/haxe/issues/11505
+	**/
+	var ?hxbVersion:Null<Int>;
+
+	/**
+		If false, no documentation
+	**/
+	var ?generateDocumentation:Null<Bool>;
+}
+
+typedef WriterConfig = {
+	/**
+		The file path for the archive. Occurrences of `$target` are replaced
+		by the name of the current target (js, hl, etc.).
+	**/
+	var archivePath:String;
+
+	/**
+		The configuration for the current target context. If it is `null`, all data
+		for the target context is generated.
+	**/
+	var ?targetConfig:Null<WriterTargetConfig>;
+
+	/**
+		The configuration for the macro context. If it is `null`, all data for the
+		macro context is generated.
+	**/
+	var ?macroConfig:Null<WriterTargetConfig>;
+}

+ 35 - 0
std/haxe/macro/Compiler.hx

@@ -24,6 +24,7 @@ package haxe.macro;
 
 import haxe.display.Display;
 import haxe.macro.Expr;
+import haxe.hxb.WriterConfig;
 
 /**
 	All these methods can be called for compiler configuration macros.
@@ -576,6 +577,40 @@ class Compiler {
 		}
 	}
 	#end
+
+	/**
+		Gets the current hxb writer configuration, if any.
+	**/
+	static public function getHxbWriterConfiguration():Null<WriterConfig> {
+		#if macro
+		return load("get_hxb_writer_config", 0)();
+		#else
+		return null;
+		#end
+	}
+
+	/**
+		Sets the hxb writer configuration to `config`. If no hxb writer configuration
+		exists, it is created.
+
+		The intended usage is
+
+		```
+		var config = Compiler.getHxbWriterConfiguration();
+		config.archivePath = "newPath.zip";
+		// Other changes
+		Compiler.setHxbWriterConfiguration(config);
+		```
+
+		If `config` is `null`, hxb writing is disabled.
+
+		@see haxe.hxb.WriterConfig
+	**/
+	static public function setHxbWriterConfiguration(config:Null<WriterConfig>) {
+		#if macro
+		load("set_hxb_writer_config", 1)(config);
+		#end
+	}
 }
 
 enum abstract IncludePosition(String) from String to String {

+ 1 - 1
tests/misc/projects/Issue10844/user-defined-define-json-fail.hxml.stderr

@@ -1,3 +1,3 @@
 (unknown) : Uncaught exception Could not read file define.jsno
-$$normPath(::std::)/haxe/macro/Compiler.hx:505: characters 11-39 : Called from here
+$$normPath(::std::)/haxe/macro/Compiler.hx:506: characters 11-39 : Called from here
 (unknown) : Called from here

+ 1 - 1
tests/misc/projects/Issue10844/user-defined-meta-json-fail.hxml.stderr

@@ -1,3 +1,3 @@
 (unknown) : Uncaught exception Could not read file meta.jsno
-$$normPath(::std::)/haxe/macro/Compiler.hx:494: characters 11-39 : Called from here
+$$normPath(::std::)/haxe/macro/Compiler.hx:495: characters 11-39 : Called from here
 (unknown) : Called from here

+ 1 - 1
tests/misc/projects/Issue10844/user-defined-meta-json-indent-fail.hxml.stderr

@@ -1,3 +1,3 @@
 (unknown) : Uncaught exception Could not read file meta.jsno
-  $$normPath(::std::)/haxe/macro/Compiler.hx:494: characters 11-39 : Called from here
+  $$normPath(::std::)/haxe/macro/Compiler.hx:495: characters 11-39 : Called from here
   (unknown) : Called from here

+ 2 - 2
tests/misc/projects/Issue10844/user-defined-meta-json-pretty-fail.hxml.stderr

@@ -2,9 +2,9 @@
 
    | Uncaught exception Could not read file meta.jsno
 
-    ->  $$normPath(::std::)/haxe/macro/Compiler.hx:494: characters 11-39
+    ->  $$normPath(::std::)/haxe/macro/Compiler.hx:495: characters 11-39
 
-    494 |   var f = sys.io.File.getContent(path);
+    495 |   var f = sys.io.File.getContent(path);
         |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
         | Called from here
 

+ 2 - 2
tests/unit/compile-hxb-jvm-roundtrip.hxml

@@ -1,7 +1,7 @@
 compile-jvm-only.hxml
---hxb bin/hxb/jvm.zip
+--hxb hxb-config/jvm.json
 
 --next
 
 compile-jvm-only.hxml
---hxb-lib bin/hxb/jvm.zip
+--hxb-lib bin/hxb/unit.java.zip

+ 10 - 0
tests/unit/hxb-config/jvm.json

@@ -0,0 +1,10 @@
+{
+	"archivePath": "bin/hxb/unit.$target.zip",
+	"targetConfig": {
+		"exclude": ["unit.TestMainNow"],
+		"generateDocumentation": false
+	},
+	"macroConfig": {
+		"generateDocumentation": false
+	}
+}

+ 1 - 3
tests/unit/src/unit/TestMain.hx

@@ -31,9 +31,7 @@ function main() {
 	cs.system.threading.Thread.CurrentThread.CurrentCulture = new cs.system.globalization.CultureInfo('tr-TR');
 	cs.Lib.applyCultureChanges();
 	#end
-	#if !macro
-	trace("Generated at: " + HelperMacros.getCompilationDate());
-	#end
+	TestMainNow.printNow();
 	trace("START");
 	#if flash
 	var tf:flash.text.TextField = untyped flash.Boot.getTrace();

+ 9 - 0
tests/unit/src/unit/TestMainNow.hx

@@ -0,0 +1,9 @@
+package unit;
+
+class TestMainNow {
+	static public function printNow() {
+		#if !macro
+		trace("Generated at: " + HelperMacros.getCompilationDate());
+		#end
+	}
+}