I need to compile a Chicken Scheme project containing multiple source files, but I'm getting errors.
According to the manual and this SO answer, I need to put (declare)
s in my sources. Why the compiler can't just see that I'm importing the other source is beyond me, but meh.
The problem is, even if I put the (declare)
s in, the compiler complains about the (import)
s and (use)
s.
infinity.filesystem.scm:
(use bindings filepath posix)
(declare (uses infinity.general.scm))
(load-relative "infinity.general.scm")
(module infinity.filesystem (with-open-file make-absolute-path with-temporary-directory with-chdir)
(import scheme filepath posix infinity.general)
(begin-for-syntax
(use bindings chicken)
(import infinity.general))
...etc...
infinity.general.scm:
(declare (unit infinity.general.scm))
(require-extension srfi-1 srfi-13 format data-structures ansi-escape-sequences basic-sequences)
(module infinity.general (bind+ format-ansi repeat-string join-strings pop-chars! inc! dec!
take* drop* take-right* drop-right* ends-with? take-where)
(import scheme chicken srfi-1 srfi-13 data-structures ansi-escape-sequences basic-sequences bindings ports format)
...etc...
Command:
$ csc -uses bindings.o -uses infinity.general.o -c infinity.filesystem.scm -o infinity.filesystem.o
Compiler says:
Syntax error (import): cannot import from undefined module
and
unbound variable: use
If I just remove the import
and use
declarations for "infinity.general", the file compiles. However, I have two problems with this:
.o
file actually work, in the absence of import
and use
clauses? Or will it complain about missing code at runtime?csi
requires that my code contains (import)
and (use)
declarations, whereas csc
requires that it does not. I, however, require that my code works in both csi
and csc
!
How can I solve this, please?
Why the compiler can't just see that I'm importing the other source is beyond me, but meh.
Declares are used to determine dependencies: the compiler needs to know in what order (and if at all) to invoke a particular toplevel, to ensure the right code is initialized before any of the globals from that unit can be used. When everything is being compiled separately, the compiler wouldn't know when to insert calls to toplevels. The -uses
switch you pass to csc
is redundant: csc -uses foo
is equivalent to putting (declare (uses foo))
in the source code. Passing -uses foo.o
doesn't do anything with the file foo.o
as far as I can tell.
In your code snippet, you're using load
, which is not the correct way to include code at compile-time: load
will read and evaluate the target file at run time. Instead, you should omit the load
completely: the declare
already takes care of the dependency; you just need to link them together.
Also, it's not very common to use filenames as module/unit names, though it should work.
If I just remove the import and use declarations for "infinity.general", the file compiles. However, I have two problems with this:
1) Will the resulting .o file actually work, in the absence of import and use clauses? Or will it complain about missing code at runtime?
You'll need to keep the import
expressions, or the program shouldn't compile. If it does compile, there's something strange going on. You don't need use
when you link everything together statically. If you're using dynamic linking, you will get a runtime error.
The error you get about unbound variable: use
is because you're using use
in a begin-for-syntax
block. You'll probably just need to (import-for-syntax chicken)
, as per your other SO question.
2) csi requires that my code contains (import) and (use) declarations, whereas csc requires that it does not. I, however, require that my code works in both csi and csc!
It looks like you're approaching this too quickly: You are writing a complete program and at the same time trying to make it run compiled and interpreted, without first building an understanding of how the system works.
At this point, it's probably a good idea to experiment first with a tiny project consisting of two files. Then you can figure out how to compile an executable that works from code that also works in the interpreter. Then, use this knowledge to build the actual program. If at any point something breaks, you can always go back to the minimal case and figure out what you're doing differently.
This will also help in getting support, as you would be able to present a complete, but minimal set of files, and people will be able to tell you much quicker where you went wrong, or whether you've found a bug.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With