📄 using-the-compiler.html
字号:
1 (* n (fac (- n 1))) ) )(write (fac 10))(newline)</PRE><a name="compiling-your-program"></a><h4>Compiling your program</h4><p>Compile the file <tt>foo.scm</tt>:</p><pre>% csc foo.scm</pre><p>This will produce the <tt>foo</tt> executable:</p><pre>% lsfoo foo.scm</pre><a name="running-your-program"></a><h4>Running your program</h4><p>To run your newly compiled executable use:</p><pre>% foo3628800</pre><p>If you get a <tt>foo: command not found</tt> error, you might want to try with <tt>./foo</tt> instead (or, in Unix machines, modify your <tt>PATH</tt> environment variable to include your current directory).</p><a name="an-example-with-multiple-files"></a><h3>An example with multiple files</h3><p>If multiple bodies of Scheme code are to be combined into a single executable, then we have to compile each file and link the resulting object files together with the runtime system.</p><p>Let's consider an example where your program consists of multiple source files.</p><a name="writing-your-source-files"></a><h4>Writing your source files</h4><p>The declarations in these files specify which of the compiled files is the main module, and which is the library module. An executable can only have one main module, since a program has only a single entry-point. In this case <tt>foo.scm</tt> is the main module, because it doesn't have a <tt>unit</tt> declaration:</p><PRE><I><FONT COLOR="#B22222">;;; foo.scm</FONT></I><I><FONT COLOR="#B22222">; The declaration marks this source file as dependant on the symbols provided</FONT></I><I><FONT COLOR="#B22222">; by the bar unit:</FONT></I>(declare (uses bar))(write (fac 10)) (newline)</PRE><p><tt>bar.scm</tt> will be our library:</p><PRE><I><FONT COLOR="#B22222">;;; bar.scm</FONT></I><I><FONT COLOR="#B22222">; The declaration marks this source file as the bar unit. The names of the</FONT></I><I><FONT COLOR="#B22222">; units and your files don't need to match.</FONT></I>(declare (unit bar))(<B><FONT COLOR="#A020F0">define</FONT></B> (<B><FONT COLOR="#0000FF">fac</FONT></B> n) (<B><FONT COLOR="#A020F0">if</FONT></B> (zero? n) 1 (* n (fac (- n 1))) ) )</PRE><a name="compiling-and-running-your-program"></a><h4>Compiling and running your program</h4><p>You should compile your two files with the following commands:</p><pre>% csc -c bar.scm% csc -c foo.scm</pre><p>That should produce two files, <tt>bar.o</tt> and <tt>foo.o</tt>. They contain the code from your source files in compiled form.</p><p>To link your compiled files use the following command:</p><pre>% csc foo.o bar.o -o foo</pre><p>This should produce the <tt>foo</tt> executable, which you can run just as in the previous example. At this point you can also erase the <tt>*.o</tt> files.</p><p>You could avoid one step and link the two files just as <tt>foo.scm</tt> is compiled:</p><pre>% csc -c bar.scm% csc foo.scm bar.o -o foo</pre><p>Note that if you want to distribute your program, you might want it to follow the GNU Coding Standards. One relatively easy way to achieve this is to use Autoconf and Automake, two tools made for this specific purpose. </p><a name="extending-the-compiler"></a><h2>Extending the compiler</h2><p>The compiler supplies a couple of hooks to add user-level passes to the compilation process. Before compilation commences any Scheme source files or compiled code specified using the <tt>-extend</tt> option are loaded and evaluated. The parameters <tt>user-options-pass, user-read-pass, user-preprocessor-pass, user-pass, user-pass-2</tt> and <tt>user-post-analysis-pass</tt> can be set to procedures that are called to perform certain compilation passes instead of the usual processing (for more information about parameters see: <a href="supported-language.html" class="internal">Supported language</a>.</p><dl><dt>[parameter] user-options-pass</dt><dd>Holds a procedure that will be called with a list of command-line arguments and should return two values: the source filename and the actual list of options, where compiler switches have their leading <tt>-</tt> (hyphen) removed and are converted to symbols. Note that this parameter is invoked <strong>before</strong> processing of the <tt>-extend</tt> option, and so can only be changed in compiled user passes.</dd><dt>[parameter] user-read-pass</dt><dd>Holds a procedure of three arguments. The first argument is a list of strings with the code passed to the compiler via <tt>-prelude</tt> options. The second argument is a list of source files including any files specified by <tt>-prologue</tt> and <tt>-epilogue</tt>. The third argument is a list of strings specified using <tt>-postlude</tt> options. The procedure should return a list of toplevel Scheme expressions.</dd><dt>[parameter] user-preprocessor-pass</dt><dd>Holds a procedure of one argument. This procedure is applied to each toplevel expression in the source file <strong>before</strong> macro-expansion. The result is macro-expanded and compiled in place of the original expression.</dd><dt>[parameter] user-pass</dt><dd>Holds a procedure of one argument. This procedure is applied to each toplevel expression <strong>after</strong> macro-expansion. The result of the procedure is then compiled in place of the original expression.</dd><dt>[parameter] user-pass-2</dt><dd>Holds a procedure of three arguments, which is called with the canonicalized node-graph as its sole argument. The result is ignored, so this pass has to mutate the node-structure to cause any effect.</dd><dt>[parameter] user-post-analysis-pass</dt><dd>Holds a procedure that will be called after every performed program analysis pass. The procedure (when defined) will be called with seven arguments: a symbol indicating the analysis pass, the program database, the current node graph, a getter and a setter-procedure which can be used to access and manipulate the program database, which holds various information about the compiled program, a pass iteration count, and an analysis continuation flag. The getter procedure should be called with two arguments: a symbol representing the binding for which information should be retrieved, and a symbol that specifies the database-entry. The current value of the database entry will be returned or <tt>#f</tt>, if no such entry is available. The setter procedure is called with three arguments: the symbol and key and the new value. The pass iteration count currently is meaningful only for the 'opt pass. The analysis continuation flag will be <tt>#f</tt> for the last 'opt pass. For information about the contents of the program database contact the author.</dd></dl><p>Loaded code (via the <tt>-extend</tt> option) has access to the library units <tt>extras, srfi-1, srfi-4, utils, regex</tt> and the pattern matching macros. Multithreading is not available.</p><p>Note that the macroexpansion/canonicalization phase of the compiler adds certain forms to the source program. These extra expressions are not seen by <tt>user-preprocessor-pass</tt> but by <tt>user-pass</tt>.</p><a name="distributing-compiled-c-files"></a><h2>Distributing compiled C files</h2><p>It is relatively easy to create distributions of Scheme projects that have been compiled to C. The runtime system of CHICKEN consists of only two handcoded C files (<tt>runtime.c</tt> and <tt>chicken.h</tt>), plus the file <tt>chicken-config.h</tt>, which is generated by the build process. All other modules of the runtime system and the extension libraries are just compiled Scheme code. The following example shows a minimal application, which should run without changes on the most frequent operating systems, like Windows, Linux or FreeBSD:</p><p>Let's take a simple example.</p><PRE><I><FONT COLOR="#B22222">; hello.scm</FONT></I>(print <B><FONT COLOR="#BC8F8F">"Hello, world!"</FONT></B>)</PRE><pre> % chicken hello.scm -optimize-level 3 -output-file hello.c</pre><p>Compiled to C, we get <tt>hello.c</tt>. We need the files <tt>chicken.h</tt> and <tt>runtime.c</tt>, which contain the basic runtime system, plus the three basic library files <tt>library.c</tt>, <tt>eval.c</tt> and <tt>extras.c</tt> which contain the same functionality as the library linked into a plain CHICKEN-compiled application, or which is available by default in the interpreter, <tt>csi</tt>:</p><pre> % cd /tmp %echo '(print "Hello World.")' > hello.scm % cp $CHICKEN_BUILD/runtime.c . % cp $CHICKEN_BUILD/library.c . % cp $CHICKEN_BUILD/eval.c . % cp $CHICKEN_BUILD/extras.c . % gcc -static -Os -fomit-frame-pointer runtime.c library.c eval.c \ extras.c hello.c -o hello -lm</pre><p>Now we have all files together, and can create an tarball containing all the files:</p><pre>% tar cf hello.tar Makefile hello.c runtime.c library.c eval.c extras.c chicken.h% gzip hello.tar</pre><p>This is naturally rather simplistic. Things like enabling dynamic loading, estimating the optimal stack-size and selecting supported features of the host system would need more configuration- and build-time support. All this can be addressed using more elaborate build-scripts, makefiles or by using autoconf/automake.</p><p>Note also that the size of the application can still be reduced by removing <tt>extras</tt> and <tt>eval</tt> and compiling <tt>hello.scm</tt> with the <tt>-explicit-use</tt> option.</p><p>For more information, study the CHICKEN source code and/or get in contact with the author.</p><p>Previous: <a href="index.html" class="internal">index.html</a></p><p>Next: <a href="using-the-interpreter.html" class="internal">Using the interpreter</a></p></body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -