···46464747(* Derived properties *)
48484949-let is_renamed {phase; _} = (phase = Renamed)
4949+let is_renamed {phase; _} = (phase <> Original)
50505151let bindir {prefix; bindir_suffix; _} =
5252 Filename.concat prefix bindir_suffix
···180180 let value =
181181 String.sub binding (equals + 1) (String.length binding - equals - 1)
182182 in
183183- if is_path_env name then
183183+ if phase <> Execution && is_path_env name then
184184 if Sys.win32 then
185185 if String.index_opt bindir ';' <> None then
186186 Printf.sprintf "%s=\"%s\";%s" name bindir value
···226226 highlighted. If argv0 is specified, then the original program executable is
227227 also shown. *)
228228let display_execution level status pid ~runtime program argv0 args
229229- ({pp_path; verbose; serial; _} as env) =
229229+ ({pp_path; verbose; serial; phase; _} as env) =
230230 let pp_program style program f = function
231231 | Some argv0 ->
232232 Format.fprintf f "@{<%s>%s (from %a)@}"
···269269 if serial <> !last_environment then begin
270270 last_environment := serial;
271271 Format.printf "\
272272- @{<inline_code>> @}@{<loc>Environment@}\n\
273273- @{<inline_code>> @} @{<loc>PATH=%a:$PATH@}\n"
274274- pp_path (bindir env);
272272+ @{<inline_code>> @}@{<loc>Environment@}\n";
273273+ if phase <> Execution then
274274+ Format.printf "\
275275+ @{<inline_code>> @} @{<loc>PATH=%a:$PATH@}\n"
276276+ pp_path (bindir env);
275277 if not Sys.win32 then
276278 Format.printf "\
277279 @{<inline_code>> @} @{<loc>%s=%a:$%s@}\n"
···428430 (* The tests are easier to write with the assumption that shims are
429431 simply ignored in the Original phase (otherwise they all begin
430432 [Env.is_renamed env && (* ... *)] *)
431431- let runtime = runtime && phase = Renamed in
433433+ let runtime = runtime && phase <> Original in
432434 let env =
433433- if phase = Renamed && (stubs || stdlib) then
435435+ if phase <> Original && (stubs || stdlib) then
434436 apply_shims ~stubs ~stdlib env
435437 else
436438 env
···449451 fails without each shim in turn. The final entry in the strategy must be
450452 the request itself. *)
451453 let test_without cond shim strategy =
452452- if phase = Renamed && cond then
454454+ if phase <> Original && cond then
453455 shim env :: strategy
454456 else
455457 strategy
+1-1
testsuite/tools/environment.mli
···3737 with [LD_LIBRARY_PATH] / [DYLD_LIBRARY_PATH] set or updated). *)
38383939val is_renamed : t -> bool
4040-(** [is_renamed t] if [~phase = Renamed] *)
4040+(** [is_renamed t] if [~phase <> Original] *)
41414242val test_root : t -> string
4343(** Retrieves the [~test_root] passed to {!make}. *)
+1-1
testsuite/tools/harness.ml
···2323 | Custom
2424 | Vanilla
25252626- type phase = Original | Renamed
2626+ type phase = Original | Execution | Renamed
27272828 type mode = Bytecode | Native
2929
+5-2
testsuite/tools/harness.mli
···39394040 (** Test harness phases. *)
4141 type phase =
4242- | Original (* Compiler installed in its original configured prefix. *)
4343- | Renamed (* Compiler moved to a different prefix from its configuration. *)
4242+ | Original (* Compiler installed in its original configured prefix. *)
4343+ | Execution (* Executing programs built by the compiler installed in its
4444+ original prefix after the compiler has been moved to a
4545+ different prefix. *)
4646+ | Renamed (* Compiler moved to a different prefix from its configuration. *)
44474548 (* Tooling modes. *)
4649 type mode =
+27
testsuite/tools/poisonedruntime.c
···11+/**************************************************************************/
22+/* */
33+/* OCaml */
44+/* */
55+/* David Allsopp, University of Cambridge & Tarides */
66+/* */
77+/* Copyright 2025 David Allsopp Ltd. */
88+/* */
99+/* All rights reserved. This file is distributed under the terms of */
1010+/* the GNU Lesser General Public License version 2.1, with the */
1111+/* special exception on linking described in the file LICENSE. */
1212+/* */
1313+/**************************************************************************/
1414+1515+/* Micro-program used to sit in PATH to test local path search for bytecode
1616+ executables. */
1717+1818+#define CAML_INTERNALS
1919+#include <caml/callback.h>
2020+#include <stdio.h>
2121+2222+int main_os(int argc, char_os **argv)
2323+{
2424+ printf("The poisoned runtime has been invoked!\n"
2525+ "This suggests something is wrong in stdlib/header.c\n");
2626+ return 1;
2727+}
+68-24
testsuite/tools/testLinkModes.ml
···364364 tendered && not target_launcher_searches_for_ocamlrun
365365 && (config.has_relative_libdir = None || not (Environment.is_renamed env))
366366 in
367367- let rec run env =
367367+ let rec run ~re_executing env =
368368 let runs =
369369 test_runs usr_bin_sh test_program_path test_program
370370 config env ~via_ocamlrun in
371371 let execute ({argv0; prefix_path_with_cwd}, outcome) =
372372 let expected_executable_name, expected_exit_code, expected_argv0 =
373373 match outcome with
374374- | Fail code -> "", code, ""
375375- | Success {executable_name; argv0} -> executable_name, 0, argv0
374374+ | Fail code ->
375375+ "", code, ""
376376+ | Success {executable_name; argv0} ->
377377+ (* Systems which don't have caml_executable_name get particularly
378378+ fiddly here, because they can fail for multiple reasons in this
379379+ test! Any tendered executable which was expected to succeed is
380380+ set to fail here, since the shim for CAML_LD_LIBRARY_PATH will
381381+ not be applied. *)
382382+ if tendered && with_unix && Harness.no_caml_executable_name
383383+ (* Passing the executable directly to ocamlrun will fail if
384384+ ocamlrun isn't configured with a relative libdir *)
385385+ && (not via_ocamlrun || config.has_relative_libdir = None)
386386+ && (re_executing || Environment.is_renamed env
387387+ && config.has_relative_libdir = None) then
388388+ "", 134, ""
389389+ else
390390+ executable_name, 0, argv0
376391 in
377377- let stubs = tendered && with_unix && config.has_relative_libdir = None in
392392+ let stubs =
393393+ tendered && with_unix
394394+ (* The programs compiled before the prefix is renamed are intentionally
395395+ run without the runtime in PATH in order to test the bytecode
396396+ launcher's searching in the image directory before PATH. A side
397397+ effect of this is that ld.conf then can't be found, because the
398398+ runtime copied to the testsuite directory doesn't have ld.conf in the
399399+ correct place. The shim is skipped for systems which don't have
400400+ caml_executable_name because otherwise we'd have a test which fails
401401+ in the Original phase and succeeds in the Execution phase, which is a
402402+ special case too far! *)
403403+ && (not Harness.no_caml_executable_name
404404+ && (config.has_relative_libdir = None
405405+ || not via_ocamlrun && re_executing))
406406+ in
378407 run_program
379408 env config ~runtime:via_ocamlrun ~stubs
380409 test_program_path ~prefix_path_with_cwd expected_executable_name
···386415 if Environment.is_renamed env then
387416 (Harness.erase_file test_program_path; `None)
388417 else
389389- `Some run
418418+ `Some (run ~re_executing:true)
390419 in
391391- `Some run
420420+ `Some (run ~re_executing:false)
392421393422(* Describe the various ways in which executables can be produced by our two
394423 compilers... *)
395424type linkage =
396396-| Default_ocamlc of launch_mode
425425+| Default_ocamlc of launch_mode * Config.search_method
397426| Default_ocamlopt
398427| Custom_runtime of runtime_mode
399428| Output_obj of compiler * runtime_mode
···462491 0
463492 in
464493 match test with
465465- | Default_ocamlc Header_exe ->
466466- let args =
467467- if config.bytecode_shebangs_by_default then
468468- ["-launch-method"; "exe"]
469469- else
470470- [] in
471471- f ~tendered:true args
472472- | Default_ocamlc Header_shebang ->
494494+ | Default_ocamlc(launch_method, search_method) ->
473495 let args =
474474- if config.bytecode_shebangs_by_default then
475475- []
476476- else
477477- ["-launch-method"; "sh"] in
478478- f ~tendered:true args
496496+ match launch_method with
497497+ | Header_exe when config.bytecode_shebangs_by_default ->
498498+ ["-launch-method"; "exe"]
499499+ | Header_shebang when not config.bytecode_shebangs_by_default ->
500500+ ["-launch-method"; "sh"]
501501+ | _ ->
502502+ [] in
503503+ let target_launcher_searches_for_ocamlrun =
504504+ (search_method <> Config.Disable)
505505+ in
506506+ let param =
507507+ match search_method with
508508+ | Disable -> "disable"
509509+ | Fallback -> "fallback"
510510+ | Enable -> "enable"
511511+ in
512512+ let args = "-runtime-search" :: param :: args in
513513+ f ~target_launcher_searches_for_ocamlrun ~tendered:true args
479514 | Default_ocamlopt ->
480515 f ~mode:Native []
481516 | Custom_runtime Static ->
···700735 pp_path ocamlc_where pp_path ocamlopt_where;
701736 let compile_test = compile_test sh config env in
702737 let tests = [
703703- compile_test (Default_ocamlc Header_exe)
704704- "byt_default_exe" "with tender";
738738+ compile_test (Default_ocamlc(Header_exe, Disable))
739739+ "byt_default_exe_disable" "with absolute tender";
740740+ compile_test (Default_ocamlc(Header_exe, Fallback))
741741+ "byt_default_exe_fallback" "with fallback tender";
742742+ compile_test (Default_ocamlc(Header_exe, Enable))
743743+ "byt_default_exe_enable" "with relocatable tender";
705744 compile_test (Custom_runtime Static)
706745 "custom_static" "-custom static runtime";
707746 compile_test (Custom_runtime Shared)
···731770 ] in
732771 let tests =
733772 if Config.shebangscripts then
734734- (compile_test (Default_ocamlc Header_shebang) "byt_default_sh" "with #!")
735735- :: tests
773773+ (compile_test (Default_ocamlc(Header_shebang, Disable))
774774+ "byt_default_sh_disable" "with absolute #!") ::
775775+ (compile_test (Default_ocamlc(Header_shebang, Fallback))
776776+ "byt_default_sh_fallback" "with fallback #!") ::
777777+ (compile_test (Default_ocamlc(Header_shebang, Enable))
778778+ "byt_default_sh_enable" "with relocatable #!") ::
779779+ tests
736780 else
737781 tests in
738782 Printf.printf "Running programs\n%!";
+17-3
testsuite/tools/test_in_prefix.ml
···6868 TestBytecodeBinaries.run config env;
6969 TestLinkModes.run ~sh config env
70707171+let rename_exe_in_test_root env from_base to_base =
7272+ Sys.rename (Environment.in_test_root env (Harness.exe from_base))
7373+ (Environment.in_test_root env (Harness.exe to_base))
7474+7175let () =
7276 let ~config, ~pwd, ~prefix, ~bindir:_, ~bindir_suffix, ~libdir,
7377 ~libdir_suffix, ~summarise_only, ~verbose =
···215219 pp_path prefix;
216220 Sys.rename new_prefix prefix);
217221 let env =
218218- make_env ~phase:Renamed ~prefix:new_prefix ~bindir_suffix ~libdir_suffix in
222222+ make_env ~phase:Execution ~prefix:new_prefix ~bindir_suffix ~libdir_suffix
223223+ in
219224 (* 3. Re-run the test programs compiled with the normal prefix *)
220225 Printf.printf "Re-running test programs\n%!";
221221- List.iter
222222- (function `Some f -> assert (f env = `None) | `None -> ()) programs;
226226+ (* Verify that the searching runtimes are searching the directory containing
227227+ the program itself first. *)
228228+ let runtime = "ocamlrun" in
229229+ rename_exe_in_test_root env ("test-" ^ runtime) runtime;
230230+ Fun.protect
231231+ ~finally:(fun () -> rename_exe_in_test_root env runtime ("test-" ^ runtime))
232232+ (fun () ->
233233+ List.iter
234234+ (function `Some f -> assert (f env = `None) | `None -> ()) programs);
235235+ let env =
236236+ make_env ~phase:Renamed ~prefix:new_prefix ~bindir_suffix ~libdir_suffix in
223237 (* 4. Finally re-run the main test battery in the new prefix *)
224238 Compmisc.init_path ~standard_library:libdir ();
225239 let programs = run_tests env in