@@ -433,6 +433,9 @@ module Poll = struct
433433
434434 let ocaml_link_flags : string list Lazy.t =
435435 lazy (snd (Lazy. force ocaml_include_and_lib_flags))
436+
437+ let c_runtime_dir : File.t Lazy.t =
438+ lazy File. (Lazy. force ocaml_runtime_dir /. ./ " runtime_c" )
436439end
437440
438441(* *{1 Building rules}*)
@@ -449,12 +452,16 @@ module Var = struct
449452 let catala_exe = make " CATALA_EXE"
450453 let catala_flags = make " CATALA_FLAGS"
451454 let catala_flags_ocaml = make " CATALA_FLAGS_OCAML"
455+ let catala_flags_c = make " CATALA_FLAGS_C"
452456 let catala_flags_python = make " CATALA_FLAGS_PYTHON"
453457 let clerk_flags = make " CLERK_FLAGS"
454458 let ocamlc_exe = make " OCAMLC_EXE"
455459 let ocamlopt_exe = make " OCAMLOPT_EXE"
456460 let ocaml_flags = make " OCAML_FLAGS"
457461 let runtime_ocaml_libs = make " RUNTIME_OCAML_LIBS"
462+ let cc_exe = make " CC"
463+ let c_flags = make " CFLAGS"
464+ let runtime_c_libs = make " RUNTIME_C_LIBS"
458465
459466 (* * Rule vars, Used in specific rules *)
460467
@@ -484,6 +491,12 @@ let base_bindings catala_exe catala_flags build_dir include_dirs test_flags =
484491 | "-O" | "--optimize" | "--closure-conversion" -> true | _ -> false )
485492 test_flags
486493 in
494+ let catala_flags_c =
495+ List. filter
496+ (function
497+ | "-O" | "--optimize" -> true | _ -> false )
498+ test_flags
499+ in
487500 let catala_flags_python =
488501 List. filter
489502 (function
@@ -504,6 +517,7 @@ let base_bindings catala_exe catala_flags build_dir include_dirs test_flags =
504517 ];
505518 Nj. binding Var. catala_flags (catala_flags @ includes);
506519 Nj. binding Var. catala_flags_ocaml catala_flags_ocaml;
520+ Nj. binding Var. catala_flags_c catala_flags_c;
507521 Nj. binding Var. catala_flags_python catala_flags_python;
508522 Nj. binding Var. clerk_flags
509523 (" -e"
@@ -515,6 +529,11 @@ let base_bindings catala_exe catala_flags build_dir include_dirs test_flags =
515529 Nj. binding Var. ocamlopt_exe [" ocamlopt" ];
516530 Nj. binding Var. ocaml_flags (ocaml_flags @ includes);
517531 Nj. binding Var. runtime_ocaml_libs (Lazy. force Poll. ocaml_link_flags);
532+ Nj. binding Var. cc_exe [" cc" ];
533+ Nj. binding Var. runtime_c_libs [" -I" ^ Lazy. force Poll. c_runtime_dir;
534+ " -L" ^ Lazy. force Poll. c_runtime_dir;
535+ " -lcatala_runtime" ; " -lgmp" ];
536+ Nj. binding Var. c_flags ([" -std=c89" ; " -pedantic" ; " -Wall" ; " -Wno-unused-variable" ; " -Werror" ; Var. (! runtime_c_libs)] @ includes);
518537 ]
519538
520539let [@ ocamlformat " disable" ] static_base_rules =
@@ -552,6 +571,25 @@ let[@ocamlformat "disable"] static_base_rules =
552571 ]
553572 ~description: [" <ocaml>" ; " ⇒" ; ! output];
554573
574+ Nj. rule " catala-c"
575+ ~command: [! catala_exe; " c" ; ! catala_flags; ! catala_flags_c;
576+ ! input; " -o" ; ! output]
577+ ~description: [" <catala>" ; " c" ; " ⇒" ; ! output];
578+
579+ Nj. rule " c-object"
580+ ~command:
581+ [! cc_exe; ! input; ! c_flags; " -c" ; " -o" ; ! output]
582+ ~description: [" <cc>" ; " ⇒" ; ! output];
583+
584+ Nj. rule " c-exec"
585+ ~command: [
586+ ! cc_exe;
587+ shellout [! catala_exe; " depends" ;
588+ " --prefix=" ^ ! builddir; " --extension=c.o" ;
589+ ! catala_flags; ! orig_src];
590+ ! input; ! c_flags; " -o" ; ! output]
591+ ~description: [" <cc>" ; " ⇒" ; ! output];
592+
555593 Nj. rule " python"
556594 ~command: [! catala_exe; " python" ; ! catala_flags; ! catala_flags_python;
557595 ! input; " -o" ; ! output]
@@ -607,12 +645,24 @@ let gen_build_statements
607645 in
608646 let ml_file = target_file " ml" in
609647 let py_file = target_file " py" in
610- let ocaml, python =
648+ let c_file = target_file " c" in
649+ let h_file = target_file " h" in
650+ let ocaml, c, python =
611651 if item.extrnal then
612652 ( Nj. build " copy"
613653 ~implicit_in: [inc srcv]
614654 ~inputs: [src -. - " ml" ]
615655 ~outputs: [ml_file],
656+ List. to_seq [
657+ Nj. build " copy"
658+ ~implicit_in: [inc srcv]
659+ ~inputs: [src -. - " c" ]
660+ ~outputs: [c_file];
661+ Nj. build " copy"
662+ ~implicit_in: [inc srcv]
663+ ~inputs: [src -. - " h" ]
664+ ~outputs: [h_file]
665+ ],
616666 Nj. build " copy"
617667 ~implicit_in: [inc srcv]
618668 ~inputs: [src -. - " py" ]
@@ -621,6 +671,12 @@ let gen_build_statements
621671 ( Nj. build " catala-ocaml"
622672 ~inputs: [inc srcv]
623673 ~implicit_in: [! Var. catala_exe] ~outputs: [ml_file],
674+ Seq. return
675+ (Nj. build " catala-c"
676+ ~inputs: [inc srcv]
677+ ~implicit_in: [! Var. catala_exe]
678+ ~outputs: [c_file]
679+ ~implicit_out: [h_file]),
624680 Nj. build " python"
625681 ~inputs: [inc srcv]
626682 ~implicit_in: [! Var. catala_exe] ~outputs: [py_file] )
@@ -659,11 +715,26 @@ let gen_build_statements
659715 in
660716 [obj; modexec]
661717 in
718+ let cc =
719+ Nj. build " c-object"
720+ ~inputs: [c_file]
721+ ~implicit_in: (! Var. catala_exe :: h_file :: List. map (modfile " .h" ) modules)
722+ ~outputs: [target_file " c.o" ]
723+ ::
724+ if item.module_def <> None then []
725+ else
726+ [ Nj. build " c-exec"
727+ ~implicit_in: (target_file " c.o" :: List. map (modfile " .c.o" ) modules)
728+ ~outputs: [target_file " c.exe" ]
729+ ~vars: [Var. orig_src, [inc srcv]] ]
730+ in
662731 let expose_module =
663732 match item.module_def with
664733 | Some m when List. mem (dirname src) include_dirs ->
665- Some (Nj. build " phony" ~outputs: [m ^ " @module" ] ~inputs: [modd m])
666- | _ -> None
734+ [Nj. build " phony" ~outputs: [m ^ " @module" ] ~inputs: [modd m];
735+ Nj. build " phony" ~outputs: [m ^ " .h" ; m ^ " .c.o" ]
736+ ~inputs: [modfile " .h" m; modfile " .c.o" m]]
737+ | _ -> []
667738 in
668739 let interp_deps =
669740 ! Var. catala_exe
@@ -715,9 +786,11 @@ let gen_build_statements
715786 Seq. return def_src;
716787 Seq. return include_deps;
717788 Option. to_seq module_deps;
718- Option . to_seq expose_module;
789+ List . to_seq expose_module;
719790 Seq. return ocaml;
720791 List. to_seq ocamlopt;
792+ c;
793+ List. to_seq cc;
721794 Seq. return python;
722795 List. to_seq tests;
723796 Seq. return interpret;
0 commit comments