Apparently my previous question was too broad. So here's the question again, simplified, and with example source code.
I'm trying to compile a Chicken Scheme project containing multiple files:
test-a.scm:
#!/usr/bin/csi -script
(declare (unit test-a))
(declare (uses test-b))
(load "test-b.scm")
(use test-b)
(test-syntax)
test-b.scm:
(declare (unit test-b))
(module test-b *
(import scheme chicken)
(define-syntax test-syntax
(syntax-rules ()
((_)
(print "In test-syntax")))))
According to the official manual, I should do it like this:
csc -c test-b.scm
csc -c test-a.scm
csc test-a.o test-b.o -o test
What I actually get is this:
Syntax error (import): cannot import from undefined module
Things to note:
I'm calling a macro.
I have a (declare (uses clause, yet csc can't find my sources.
csc test-a.scm test-b.o -o test doesn't work either.
If I remove load, the program will not work in csi.
If I remove use, the program will not work in csi.
I need the program to work in csi.
How, without breaking compatibility with csi, can I make this compile?
There are four(!) problems here:
test-a.scm contains a unit declaration. This is incorrect; there's always one file that needs to be compiled to have a main() C function. That's the file without a unit declaration. If you study the manual page you linked more closely, it says "In this case foo.scm is the main module, because it doesn't have a unit declaration".
Since you decided to use modules, you'll need to compile test-b.scm as follows: csc -c -j test-b test-b.scm. The -j switch will cause the compiler to emit a module library test-b.import.scm, which is what the compiler is looking for when compiling test-a.scm. When an import library is missing, it will complain that the module is undefined. In the interpreter it's no issue because you load the file before importing the module that it defines.
You're using load, even in the compiled version of the program. This means that it will read and evaluate the test-b.scm file (and complain if it's missing) in every situation.
You're using use, which will require the library at runtime. This is meant for loading and importing modules defined by dynamically linked libraries.
So, to solve this, you could do it like this:
test-a.scm
#!/usr/bin/csi -script
;; Declare that this uses test-b, so that its toplevel is initialised
(declare (uses test-b))
;; No (declare (unit test-a)) because this file should generate main().
;; Because we tell the compiler what to link together and we want to
;; avoid passing all the .scm files on the csi command line, we can load
;; the test-b.scm file here, but only when interpreting:
(cond-expand
((not compiling) (load "test-b.scm"))
(else))
;; Only import the module; we take care of loading the code above,
;; or in the linking step when compiling. If we had (use test-b),
;; the library would be searched for at runtime.
;; Alternatively, (use test-b) here, but add (register-feature! 'test-b)
;; to test-b.scm, which prevents the runtime from attempting to load test-b.
(import test-b)
(test-syntax)
test-b.scm (unchanged)
(declare (unit test-b))
(module test-b *
(import scheme chicken)
(define-syntax test-syntax
(syntax-rules ()
((_)
(print "In test-syntax")))))
And, to compile it:
csc -c -j test-b test-b.scm
csc -c test-a.scm
csc test-a.o test-b.o -o test
I realise this is quite a lot of stuff to know, and tricky too and some things like the use plus register-feature! simply don't make much sense. We're attempting to make this less fiddly in CHICKEN 5, and we're also going to add a FAQ to the wiki, because this really isn't obvious and a bit of a FAQ.
The manual page you linked hasn't been changed in a long time: it completely ignores the existence of modules, for example. That's why you couldn't get it to compile, the -j switch was missing because the example files in the manual page don't define modules.
Edit:
This can be cleaned up a bit because declare is only honored by the compiler anyway. So we can move that into the cond-expand as well:
test-a.scm
#!/usr/bin/csi -script
(cond-expand
(compiling (declare (uses test-b)))
(else (load "test-b.scm")))
(import test-b)
(test-syntax)
Related
I have created a abc.scm file and tried to compile it to a binary (or whatever guile scheme compiles to) using "guild compile", "scm" and "guile" commands in terminal in Ubuntu.
For "guild compile abc.scm", I get the output "wrote `/home/tarunmaganti/.cache/guile/ccache/2.0-LE-8-2.0/home/tarunmaganti/abc.scm.go'"
I find the file and run like this - "./abc.scm.go" which says permission denied.
When I give the necessary permissions using "chmod 755" or "chmod 777", I get an error like - "bash: ./abc.scm.go: cannot execute binary file: Exec format error".
The "scm whatever-file-name.scm" just opens up the scm interpreter.
The "guile whatever-file-name.scm does nothing.
The link of official GNU/Guile Scheme isn't very helpful.
Please, help me. I would like to create a guile scheme script file. Compile it and run it as C/C++ program. Is it possible?
If compilation isn't possible, I would like to know, how to at least run the script file of GNU/guile scheme or MIT-Scheme.
{Step-by-step is highly appreciated, I'm still a beginner in using Ubuntu and also in Scheme.}
Thanks in advance.
You can use the shebang notation to create a Guile script (the -s is optional in newer versions of Guile):
#!/usr/bin/guile -s
!#
(display "Hello, world!\n")
Notice the !# on the second line. Guile treats the #! as the start of a block comment (similar to what #| is in standard Scheme), which has to be terminated using !# (similar to |# in standard Scheme).
If you want your script to pass any command-line options to Guile itself, then read about the meta switch. Here's an example of such:
#!/usr/bin/guile \
-e main -s
!#
(define (main args)
(if (null? (cdr args))
(format #t "Hello, world!~%")
(for-each (lambda (name)
(format #t "Hello, ~a!~%" name))
(cdr args))))
Apparently guile foo assumes that foo is a Scheme source file. If foo is a precompiled binary .go file it tries to treat it as a text file anyway and compile it a second time, which fails. I could not find any equivalent command line syntax for executing a pre-compiled .go file.
However, you can get almost the same effect as follows:
Write a source file foo.scm that exports a main procedure:
(define-module (foo)
#:export (main))
(define (main)
(display "Hello world!")
(newline))
Pre-compile it with guild compile -o foo.go foo.scm
Write a shell script that runs guile -C "$PWD" -c "(use-modules (foo)) (main)". The -C dir flag (capital C) tells it to load pre-compiled files from the directory dir. The -c expr flag (lowercase c) tells it to evaluate the Scheme code expr which in this case just does use-module to load the pre-compiled module and then calls our main procedure.
Guile's compiler is like Java's compiler: it produces bytecode that is then run in Guile's VM. I don't know of any way to go straight from Guile Scheme code to native code. Guile is really meant to be an extension language that allows you to add Scheme scripting to your C/C++ program.
I don't know much about MIT Scheme, but from what I can tell it also does not compile to a standalone executable. Feel free to correct me on that.
There's a way around all this, though. As long as you don't mind a dependency on libguile, you can write a wrapper in C/C++ and hand libguile a string containing your Scheme code. There's a basic example given in the Guile manual for Dia here. Create your script in a header file and wrap it in a null-terminated C string, then (after a bit of boilerplate and whatnot) evaluate it with scm_eval_string().
If you want to write Scheme and output native binaries, I've heard good things about Chicken.
I have a fresh install of mingw64 and chicken scheme but whenever I try to compile a file with csc from the command line I get the following:
error: shell command terminated with non-zero exit status 1: "gcc" "foo.o" -o "foo" -wl,--enable-auto-import -Lc:\chicken-iup\lib -L"c:\chicken-iup/lib/" -lchicken -lm -lws2_32"
foo.scm:
(define (fac n)
(if (zero? n)
1
(* n (fac (- n 1)))))
(write (fac 10))
(newline)
Could someone help in figuring out why it cant compile the file? If I have a file browser open to the C:\chicken-iup\ folder I can see it makes a .c file and then makes an .o file. The error happens I assume during the linking of the .o file but I'm not certain.
Looks like you're using chicken-iup. Looking at its web page, it looks like it's designed to work with mingw, and not mingw-w64. The "incompatible" libraries are probably because mingw-w64 is designed to link in 64-bit libraries, but the chicken-iup libraries were 32-bit.
If you want to use mingw-w64, you probably have to compile CHICKEN yourself.
I've wrote a sudoku solver in OCaml and I want to create a single executable for it.
I've got 3 files: board.ml, solver.ml and main.ml
board.ml contains the type of the board, functions to read from files, check validity, ...
solver.ml contains the functions to solve a given sudoku. solver.ml uses functions from board.ml
main.ml is a program which uses functions from both board.ml and solver.ml to solve a sudoku provided by command line arguments.
I don't use .mli files because the signatures are defined in the .ml files like:
module Board :
sig
(* signature *)
end
=
struct
(* implementations *)
end
I've already been able to do this with all the code in board.ml like:
ocamlc board.mli board.ml main.ml -o sudoku_solver
The end result should be one executable called "sudoku_solver" so I can do:
./sudoku_solver "sudoku.txt"
just use:
ocamlbuild main.native
and run it with
./main.native "sudoku.txt"
I am beginning to learn autotools in order to first understand and later extend an existing project's build system. Currently the project builds a program as it's output. The build system is quite complex consisting of several subdirectories and Makefile.am's with files generated in a maintainer-mode and so on. I would like to optionally be able to create a library using much of the same source code, reusing much of the the existing build system.
What I am imagining is a new make target so that after running configure, I can then run either make to make the program, or, say, make library to build the library. What is the correct way to do this or something with a similar effect?
I do not want to build both the library and program when I run plain make (just the program as before), and I do not want to build the program when I run make library (I only want the library).
If someone could provide a simple example, e.g. a program made up of main.c, foo.c and bar.c and a library made up of foo.c and bar.c that would be really helpful too.
EDIT
To clarify, I originally thought that the program and lib could be built entirely separately. The library contains only a subset of the code of the main program, and I believed the two were separate entities. However, things are more complicated. The program itself is built and used to output some code which is then compiled into the program in a second step (I think). I have effectively got what I want by doing the following steps.
First add a conditional to configure.ac
dnl Adds LIBRARY conditional for --enable-foolib mode to
dnl build foo as a library
AC_ARG_ENABLE(foolib,
AS_HELP_STRING([--enable-foolib],
[enable qucslib build, default: no]),
[case "${enableval}" in
yes) foolib=true ;;
no) foolib=false ;;
*) AC_MSG_ERROR([bad value ${enableval} for --enable-foolib]) ;;
esac],
[foolib=false])
AM_CONDITIONAL(FOOLIB, test x"$foolib" = x"true")
Then in the appropriate Makefile.am I did something similar to the following:
if FOOLIB
noinst_LIBRARIES = libbar.a libfoo.a
else
noinst_LIBRARIES = libbar.a
endif
bin_PROGRAMS = barprog
barprog_SOURCES = main.cpp src1.cpp src2.cpp etc.cpp
barprog_LDADD = libbar.a \
subdir1/libsubdir1.a \
subdir2/libsubdir2.a \
etcdir/libetc.a
... other stuff
if FOOLIB
libfoo_a_LIBADD = libbar.a \
subdir1/libsubdir1.a \
subdir2/libsubdir2.a \
etcdir/libetc.a
libfoo_a_SOURCES = src1.cpp src2.cpp etc.cpp
endif
Then when I want to make the library I do
configure --enable-foolib
make
This works for now, but seems kludgy. I wasn't sure though how to implement the provided answer in the build system.
If the program depends on the library, then it will not be possible to build the program without building the library. You already have the ability to build individual libraries: configure && make libfoo.a should work just fine (or make libfoo.la). If you wish a target named library, you can simply add the following to any Makefile.am:
library:
libfoo.a
(Or you may need libfoo.la. Basically, if the library is specified in Makefile.am under the LIBRARIES primary, then you would use libfoo.a, but if specified under an LTLIBRARIES primary, you would use libfoo.la.) This will only create a library target in each directory that contains a Makefile.am. If you have a complex recursive build (you should really simplify it, but that's another question), you can put something like the following in your top-level Makefile.am to build the libraries throughout the tree:
library:
cd subdir && $(MAKE) $(AM_MAKEFLAGS) library
This assumes you have added a library target to subdir/Makefile.am as described above.
To be pedantic, you might want to use $(am__cd) instead of cd, but it's not strictly necessary.
I am new to Ocaml and trying to write some small example application. I am using ocamlc version 3.11.2 under Linux Ubuntu 10.04. I want to compile two files:
a.ml
b.ml
File b.ml uses definitions from a.ml. As far as I understand, I can use ocamlc -c to perform compilation only. I can call ocamlc one final time when I have all the .cmo files to link them to an executable. Also, when compiling a file that uses definitions from another file, I have to tell the compiler in which .cmi file to find the external definitions.
So my idea was to use:
ocamlc -i -c a.ml > a.mli
ocamlc -c a.mli b.ml
ocamlc -o b a.cmo b.cmo
The first step works and produces files a.mli and a.cmo, but when running the second step I get
File "b.ml", line 1, characters 28-31:
Error: Unbound value foo
where foo is a function that is defined in a.ml and called in b.ml.
So my question is: how can I compile each source file separately and specify the interfaces to be imported on the command line? I have been looking in the documentation and as far as I can understand I have to specify the .mli files to be included, but I do not know how.
EDIT
Here some more details. File a.ml contains the definition
let foo = 5;;
File b.ml contains the expression
print_string (string_of_int foo) ^ "\n";;
The real example is bigger but with these files I already have the error I reported above.
EDIT 2
I have edited file b.ml and replaced foo with A.foo and this works (foo is visible in b.ml even though I have another compilation error which is not important for this question). I guess it is cleaner to write my own .mli files explicitly, as suggested by
It would be clearer if you showed the code that's not working. As Kristopher points out, though, the most likely problem is that you're not specifyig which module foo is in. You can specify the module explicitly, as A.foo. Or you can open A and just use the name foo.
For a small example it doesn't matter, but for a big project you should be careful not to use open too freely. You want the freedom to use good names in your modules, and if you open too many of them, the good names can conflict with each other.
First fix the unbound value issue, as explained by Jeffrey's answer.
This is a comment about the commands you're using.
Decomposing compilation in several steps is a good way to understand what's going on.
If you want to write your own a.mli, most likely to hide some values of the module A, then your command ocaml -i -c a.ml > a.mli is a good way to get a first version of the this file and then edit it. But if you're not touching a.mli, then you don't need to generate it: you can also directly enter
ocamlc -o foo a.ml b.ml
which will produce a.cmo, b.cmo and the exectuable foo.
(It will also generate a.cmi, which is the compiled version of a.mli, that you get by issuing ocamlc -c a.mli. Likewise it will also generate b.cmi).
Note that order matters: you need to provide a.ml before b.ml on the command line. This way, when compiling b.ml, the compiler has already seen a.ml and knows where to find the module A.
Some more comments:
You're right in your "As far as I understand" paragraph.
you don't really include a separate file, it's more like import in Python: the values of module A are available, but under the name A.foo. The contents of a.ml has not been copy-pasted into b.ml, rather, values of the module A, defined in a.ml and it's compiled version a.cmo have been accessed.
if you're using this module A in b.ml, you can pass any of the following on the command line before b.ml:
a.mli, which will get compiled into a.cmi
a.cmi if you've already compiled a.mli into a.cmi
a.ml or its compiled version a.cmo if you don't need to write your own a.mli, i.e. if the default interface of module A suits you. (This interface is simply every value of a.ml).