I have downloaded a large software project FriCAS which I have compiled from source and using SBCL. This was just a matter of using GNU .configure - I am a complete Lisp newbie.
However, in order to add some further functionality I have - by very carefully following directions - installed quicklisp and a few extra packages. So far so good.
Here's my issue: I am trying to compile an external lisp file for use in the system. I need to make quicklisp and its packages visible to the compiler. So I've copied my .sbclrc file to the top of my lisp file:
#-quicklisp
(let ((quicklisp-init (merge-pathnames "quicklisp/setup.lisp"
(user-homedir-pathname))))
(when (probe-file quicklisp-init)
(load quicklisp-init)))
I have followed this with
(eval-when (:compile-toplevel)
(ql:quickload "f2cl-lib"))
I have already installed f2cl-lib with quicklisp. However, my compiler (within FriCAS) immediately aborts with
; caught ERROR:
; READ error during COMPILE-FILE:
;
; Package QL does not exist.
I'm a bit stumped here - there's probably something trivial and obvious which is missing, but as I say from a newbie perspective I don't know what it is.
Looks like a FAQ. See also the documentation for eval-when.
The File Compiler
Remember, a file compiler compiles forms and does not execute them. It just generates code for later execution. Generally. Though, in Common Lisp there are some exceptions to this rule: for example a macro, used in the source code, will be run by the file compiler. But Common Lisp also allows us to tell the file compiler to execute code at compile time, that's one of the use cases of eval-when.
Your example simplified
If you have a file:
(load "file-which-creates-package-foo")
(eval-when (:compile-toplevel)
(foo:bar))
Then the file compiler will generate code for loading the file, but it will not load the file.
Next, the file compiler sees a second form, where the file compiler is instructed to execute a statement at compile time (and only at compile time), so (foo:bar) will be executed at compile time. But it is worse: Since the loading code has not been executed yet, the package FOO is unknown, and the form (foo:bar) will be read at compile time, the reader already complains at compile time that the package FOO does not exist.
The use of EVAL-WHEN
What you need to do, is to tell the file compiler to actually load the stuff it needs during compilation. The file already contains an eval-when form, so that should give you a hint: use eval-when. It has three situations:
:compile-toplevel -> the file compiler executes the enclosed forms
:load-toplevel -> the file compiler generates code so that the code will be executed when loading the code
:execute
Make sure that those situations are mentioned, when the code should be executed.
Possible solutions
So there are possible solutions:
as above, use EVAL-WHEN to be able to execute forms by the file compiler
write the loading code into a separate file and compile/load this file before you use the package. One could also add this file to a system such that it will be loaded by the compiling the system, before the using code will be compiled.
Related
I use ADSF to organise my projects.
(asdf:defsystem :sender
:version "0.1.4"
:serial t
:depends-on (:cl-json :dexador :clsql :clsql-sqlite3)
:components ((:file "packages")
(:file "validation")
(:file "sender")))
But when I open a new repl (slime, emacs), I have to go to the packages.lisp file and evaluate the form before I can change the repl to that package with (in-package :sender).
Is there a way to make the slime repl remember my packages?
My current thinking is that I need to "run" adsf to load all my files. If so, how?
UPDATE:
Actually, I need to compile all the files manually before I can actively use them in the repl. I believe I am using asdf incorrectly.
From a .asd system definition, the steps would be:
compile the .asd file, so that you Lisp image knows about the system
C-c C-k or programmatically: (asdf:load-asd "system").
LOAD it somehow: (ql:quickload "system") to install dependencies
or (asdf:load-system "system"), but it will fail if your project has unknown dependencies, Quicklisp would download them.
avoid using cl:load for asdf systems, load-asd / load-system will do more complex stuff.
use it on the REPL. The package that was defined in a packages.lisp file should be available, because this file was declared in the .asd.
You can add stuff to your ~/.sbclrc (or similar for other implementations). Here I tell ASDF where a project lives, so I can quickload it without manually compiling the .asd before:
(pushnew "/home/vince/projets/ciel/" asdf:*central-registry* :test #'equal)
This is an "old" style not encouraged anymore by the ASDF documentation.
Or simply create a symlink for your project to ~/quicklisp/local-projects/ or ~/common-lisp/.
I wouldn't "load-system" my project in the init file, because that's a side effect that would show sometimes when I don't want it (like building an image: if that involves reading my init file, I'd have an unwanted system in it).
Saving a core image with a ton of dependencies is cool. Use it with sbcl --core …. The advantage is that it starts up instantly in the REPL, when loading all projects and dependencies would take a few seconds.
Pointers
ASDF
ASDF cookbook
ASDF manual
ASDF best practices
ASDF Build System explained
Overview
A system is an object which describes a library (or an application) which consists of: a name, a version, a list of files and subsystems, and a list of other systems it depends on. There is more.
If you want to have Lisp know a certain system, then we need to execute its defsystem form either manually or find it automatically. That ONLY makes the system definition known.
If you want to load the system's files, then you need to LOAD the SYSTEM. If you want to compile the system's files files, the you need to COMPILE the system.
So, if you want to use a package (which is a namespace), then you need to run the DEFPACKAGE form. If that form is describe in a file which is component of a system, then you need to load that system.
ASDF : a popular build system for Common Lisp
system -> library, application. It is a bunch of files and dependencies.
system definition -> not the system itself, but a description of it. Use DEFSYSTEM to describe a system
system operations -> like load-system, compile-system and others.
system registry -> Typically we want ASDF to find the systems by name. See the manual or a tutorial for ASDF.
lisp file -> some file we can compile or load
fasl file -> some compiled file we can load
package -> a namespace for symbols, that's actually a built-in feature for Common Lisp
Quicklisp -> a library manager with a selection of curated Common Lisp libraries/applications. The libraries can be loaded over the Internet. Be aware that there is little to no security when loading foreign code from the Internet.
Use a system, its components and dependencies
If you want to use a system you need to load it first. Manually or automatically.
That loading can be done automatically:
For example in an init-file for your Lisp you can load all systems you want/need. Alternative write a function which loads all systems you want.
saving an image. Some Lisps support saving an image. Thus one can load all interesting systems and then save an image. If one starts that image later, all those systems are already in memory. (side problem: getting newer versions loaded)
Is there anything like file in shell for lisp to determine file type? If not, how do you determine file tpye?
In most case pathname-type is good enough, but sometimes you may run into some files doesn't have been correct named.
The functionality of file is available in libmagic:
As of version 4.00 of the Ian Darwin/Christos Zoulas version of file, the functionality of file is incorporated into a libmagic library that is accessible via C (and C-compatible) linking;[7][8] file is implemented using that library.
Wikipedia
And there is a binding for Common Lisp.
I had to install libmagic-dev on my system, and then:
CL-USER> (ql:quickload :magicffi)
...
(:MAGICFFI)
CL-USER> (magicffi:pathname-mime #P"/bin/ls")
"application/x-sharedlib; charset=binary"
See MAGICFFI.
To learn the processes behind compilation of Ada programs (without resorting to using gpr), I've decided to compile one of my projects manually. To compile a program, I run the following command on each .adb file therein (not manually, however):
$ gcc -c src/<file>.adb -o obj/<file>.o
That compiles all the files and puts them in the obj directory.
Or rather, it would. There is a slight problem with this. I have an archive (static library) that I've generated from another project, called libapples.a, containing package Apples. The Apples package is used by the files you see me compiling above.
Since libapples.a doesn't have source files anymore (given its archive format), it's not viable (not even possible) to provide the sources of that library to the command above using -I switches; on the other hand, if I don't have the sources included, the command above comes back to me saying:
<file>.adb:<y>:<x>: file "apples.ads" not found
gnatmake: "src/<file>.adb" compilation error
I've attempted to include the library in the compilation process by using flags -L and l (which I believe is how you'd do it in C; feel free to correct me if I'm wrong). In another attempt I placed the archive right in the source directory.
How does one go about including a library in the compilation process?
apples.ads is somewhat like a header in C and you definitely need it for your file to compile. You should use -I to point gcc to the directory where apples.ads is located in.
Be aware that compiling an Ada source not only yields an object file, but also an Ada Library Information (.ali) file. You'll need that for the next step. You should not use the -o flag because it may lead to your .o and .ali files having different names.
On the other hand, since you only want to produce an object file, you should use -c to tell gcc to only compile. In other languages like C, gcc compiles and links by default; in Ada, the process is more complex.
After compilation, you need to call gnatbind on the .ali file of your main program. This generates a package that will take care of proper initialization of everything. To do that, gnatbind needs the .ali file of the Apples package! You can specify the .ali search directory with -aO.
Finally, gnatlink called on the main .ali file will link everything together. It figures out itself which object files and libraries it needs. It will append the necessary options to the linker, including the reference to libapples.a. It also compiles the package generated by gnatlink.
I don't know exactly what gnatlink will do under the hood; you could probably compile the package generated by gnatbind manually and then call the linker if you can figure out the proper arguments.
I am trying to get my head around programming with multiple modules (in different files). I don't want to load explicitly the files with ìnclude in the right order.
I am using the Atom IDE as my development platform, so I don't run julia explicitly.
when I am just using importall Datastructures (where ModuleName is the name of the module) julia complains:
LoadError: ArgumentError: Module Datastructures not found in current path.
Run `Pkg.add("Datastructures")` to install the Datastructures package.
while loading F:\dev\ai\Interpreter.jl, in expression starting on line 8
There are two ways to build a package or module in julia:
1) Use the tools in PkgDev. You can get them with Pkg.add("PkgDev") ; using PkgDev. Now you can use PkgDev.generate("MyPackageName", "MIT") (or whatever license you prefer) to build your package folder. By default, julia will build this folder in the same directory as all your other external packages. On Linux, this would ~/.julia/v0.6/ (or whatever version you are running). Also by default, this folder will be on the julia path, so you can just type using MyPackageName at the REPL to load it.
Note that julia essentially loads the package by looking for the file ~/.julia/v0.6/MyPackageName/src/MyPackageName.jl and then running it. If your module consists of multiple files, you should have all of them in the ~/.julia/v0.6/MyPackageName/src/ directory, and then have a line of code in the MyPackageName.jl file that says include("MyOtherFileOfCode.jl").
2) If you don't want to keep your package in ~/.julia/v0.6/ for some reason, or you don't want to build your package using PkgDev.generate(), you can of course just set the files up yourself.
Let's assume you want MyPackageName to be stored in the ~/MyCode directory. First, create the directory ~/MyCode/MyPackageName/. Within this directory, I strongly recommend using the same structure that julia and github use, i.e. store all your code in a directory called ~/MyCode/MyPackageName/src/.
At a minimum, you will need a file in this directory called ~/MyCode/MyPackageName/src/MyPackageName.jl (just like in the method above). This file should begin with module MyPackageName and finish with end. Then, put whatever you want in-between (including include calls to other files in the src directory if you wish).
The final step is to make sure that julia can find MyPackageName. To do this, you will need ~/MyCode to be on the julia path. To do this, use: push!(LOAD_PATH, "~/MyCode") or push!(LOAD_PATH, "~/MyCode/MyPackageName").
Maybe you don't want to have to run this command every time you want to access MyPackageName. No problem, you just need to add this line to your .juliarc.jl file, which is automatically run every time you start julia. On Linux, your .juliarc.jl file should be in your home directory, i.e. ~/.juliarc.jl. If it isn't there, you can just create it and put whatever code you want in there. If you're on a different OS, you'll have to google where to put your .juliarc.jl.
This answer turned out longer than I planned...
I'm new to OCaml, but I'm trying to figure out the equivalent of __filename, __dirname from Node. That is, I need to build a path relative to the file containing the code in question.
For reference, I'm working through Ghuloum's IACC: http://ell.io/tt$ocameel
I'm building my first compiler, and I have an utterly-simplistic ‘runtime’ file (in C — temporarily) adjacent to the compiler's source-code. I need to be able to pass the path to this file, as an argument (or a pre-compiled version, I suppose) to gcc or my linker, to have it linked against my compiler's output when I invoke the linker/assembler tooling.
(This may be a stupid question — I'm at a bit of an unknown-unknown here, “how does a compiler get the runtime to the linker”, or something like that. Any commentary about idiomatic solutions to this is welcome, even if it's not a direct answer to the above question!)
If you're running the source file directly via ocaml myfile.ml, Sys.argv.(0) will give you the path to the source file and you can use Filename.dirname to get the directory from that.
If you first compile the source file into an executable and then run the executable, Sys.argv.(0) will give you the name of the executable. In that scenario it's impossible to get the location of the source code (especially if you consider that the person running the executable might not even have the source code on their system).
If you set up your project structure, so that your sources live in src/, your compiled binary in bin/ and the compiled stdlib in lib/, you could just use Filename.dirname Sys.argv.(0) ^ "../lib" as the library path for gcc. This will work whether you run ocaml src/mycompiler.ml, bin/mycompiler or just mycompiler after installing everything to /usr/ or /usr/local/.