To develop useful multi-file applications, you will also need to know how to compile a stand-alone executable which can be invoked from the command line or scripts like any other Linux executable.
In this section we will present a complete worked-out example of implementing a simple clone of the Linux factor program, which prints out the prime factorization of each argument it is given.
Our solution consists of the following four files:
Using these we will compile a factor executable image using the standard Mythryl /usr/bin/build-an-executable-mythryl-heap-image script which gets installed with the other standard Mythryl programs when you do a make install.
The following transcript shows the contents of the required files and also the compilation process:
linux$ cat factor.api api Factor { factors: Int -> List(Int); }; linux$ cat factor.pkg package factor { fun factor_helper (i, trial_divisor, known_factors) = { if (trial_divisor > i) reverse known_factors; else if (i % trial_divisor != 0) factor_helper (i, trial_divisor + 1, known_factors); else factor_helper (i/trial_divisor, trial_divisor, trial_divisor ! known_factors); fi; fi; }; fun factors( i ) = { if (i <= 1) [i]; else factor_helper (i, 2, []); fi; }; }; linux$ cat main.pkg package main: api { main: ((String, List( String ))) -> winix__premicrothread::process::Status; } { include package trap_control_c; # trap_control_c is from src/lib/std/trap-control-c.pkg fun print_to_stderr msg = file::write ( file::stderr, string::cat msg ); fun print_factors( number, factors ) = { printf "%d:" number; map (printf " %d") factors; printf "\n"; }; fun factor_number( arg ) = { number = the (int::from_string arg); print_factors( number, factor::factors( number ) ); }; fun factor_args args = { apply factor_number args; }; fun main (name, args) = { fun run_program () = factor_args args; { catch_interrupt_signal run_program; winix__premicrothread::process::success; } except CONTROL_C_SIGNAL => { print_to_stderr [name, ": Interrupt\n"]; winix__premicrothread::process::failure; }; any => { print_to_stderr [ name, ": uncaught exception ", exceptions::exception_message any, "\n" ]; winix__premicrothread::process::failure; }; end ; }; }; linux$ cat factor.lib LIBRARY_EXPORTS api Factor pkg factor pkg main LIBRARY_COMPONENTS $ROOT/src/lib/std/standard.lib factor.api factor.pkg main.pkg linux$ build-an-executable-mythryl-heap-image factor.lib main::main _build-an-executable-mythryl-heap-image: Starting. _build-an-executable-mythryl-heap-image: main=main::main (III) _build-an-executable-mythryl-heap-image: main=main::main (after sed) _build-an-executable-mythryl-heap-image: Listing tmp-makelib-pid-26077-export.pkg: pkg xyzzy_plugh { my _ = lib7::spawn_to_disk ("factor", main::main); }; _build-an-executable-mythryl-heap-image: Listing .lib file: SUBLIBRARY_EXPORTS pkg xyzzy_plugh SUBLIBRARY_COMPONENTS $ROOT/src/lib/std/standard.lib factor.lib tmp-makelib-pid-26077-export.pkg _build-an-executable-mythryl-heap-image: Doing: "/usr/bin/mythryld" --build-an-executable-mythryl-heap-image "factor.lib" "tmp-makelib-pid-26077-export.lib" "factor" "tmp-makelib-pid-26077.COMPILED_FILES_TO_LOAD" "tmp-makelib-pid-26077.LINKARGS" parse/libfile-parser-g.pkg: Reading make file factor.lib on behalf of <toplevel> app/makelib/compilable/thawedlib-tome.pkg: Parsing source file factor.api app/makelib/compilable/thawedlib-tome.pkg: Parsing source file factor.pkg app/makelib/compilable/thawedlib-tome.pkg: Parsing source file main.pkg .../compile/compile-in-dependency-order-g.pkg: Compiling source file factor.api to object file factor.api.compiled .../compile/compile-in-dependency-order-g.pkg: Compiling source file factor.pkg to object file factor.pkg.compiled .../compile/compile-in-dependency-order-g.pkg: Compiling source file main.pkg to object file main.pkg.compiled parse/libfile-parser-g.pkg: Reading make file tmp-makelib-pid-26077-export.lib on behalf of <toplevel> parse/libfile-parser-g.pkg: Reading make file factor.lib on behalf of <toplevel> app/makelib/compilable/thawedlib-tome.pkg: Parsing source file tmp-makelib-pid-26077-export.pkg .../compile/compile-in-dependency-order-g.pkg: Compiling source file tmp-makelib-pid-26077-export.pkg to object file tmp-makelib-pid-26077-export.pkg.compiled src/app/makelib/main/makelib-g.pkg: Creating file 'tmp-makelib-pid-26077.COMPILED_FILES_TO_LOAD' src/app/makelib/main/makelib-g.pkg: Creating file 'tmp-makelib-pid-26077.LINKARGS' _build-an-executable-mythryl-heap-image: Doing: "/usr/bin/mythryl-ld" `cat "tmp-makelib-pid-26077.LINKARGS"` ---------------------------------------------------- bin/mythryl-ld: Starting bin/mythryl-ld: Exec()'ing /pub/home/cynbe/src/mythryl/mythryl7/mythryl7.110.58/mythryl7.110.58/bin/mythryl-runtime-intel32 --runtime-compiledfiles-to-load=tmp-makelib-pid-26077.COMPILED_FILES_TO_LOAD --runtime-heap=mythryld src/c/main/load-compiledfiles.c: Writing load log to mythryld-26088.load.log src/c/main/load-compiledfiles.c: Reading file tmp-makelib-pid-26077.COMPILED_FILES_TO_LOAD .../lib/heap/export-fun.c: Writing executable (heap image) /pub/home/cynbe/src/mythryl/mythryl7/mythryl7.110.58/mythryl7.110.58/factor linux$ ./factor 23 24 23: 23 24: 2 2 2 3 linux$
The above code is largely self-explanatory; you should have little difficulty adapting it to your own needs.
For your convenience, the above code is shipped in the src/app/tut/factor/ directory in the Mythryl source code distribution.
For a serious application, you will probably want to put the illustrated build-an-executable-mythryl-heap-image call in your application’s Linux Makefile. (The Mythryl makelib is not intended to replace Linux make, but rather to work with it in complementary fashion. Each does well things the other does poorly.)
The main.pkg file is mostly boilerplate that you can use unchanged in your own application except for changing the run_program function to run the code appropriate to your application.
A serious application will have many more source files and perhaps application-specific .lib libraries. Just add them to the factor.lib file (presumably appropriately renamed for your application) and Mythryl’s makelib will take care of compiling everything in the right order. (Unlike Linux make, Mythryl makelib deduces needed dependency relationships directly from the source code.)
A nontrivial application will probably support various command line options. You may wish to process them using the process_commandline package, which is a Mythryl port of the GNU getopt C package.