I have developed a module (M.hs) which depends upon 3 other modules (A.hs, B.hs and C.hs). Now I want to use the module M across multiple other projects. So I have to install this module. But for learning purpose I don't want to use cabal, I want to do it manually. I want to install it in my home dir.
What is a proper course of action? Which files to be created, copied? where? How to use this module in other project?
Additional info:
I am using Debian 6
I am using GHC 6.12
You say you don’t want to use cabal, but would you use Cabal?
cabal is the name of the command line tool provided by cabal-install which can download packages from Hackage and resolve dependencies.
Cabal is the library that Haskell code uses to drive the compilation (e.g. pre-process files, build in the right order, build variants, generate documentation) and install into the right location.
I would not recommend not using Cabal, even for learning purposes, until you want to write a replacement for it. But if you really want to do it, here is the rough outline, with enough details to figure out for a good learning experience:
Build your files with -package-name yourpkgname-version.
Link the generated files to form a libyourpkgname-version.a file.
Create a package configuration file like /var/lib/ghc/package.conf.d/mtl-2.1.2.conf, and pay attention to name, `exposed-modules, import-dirs, library-dirs and hs-libraries
Register package by passing it to ghc-pkg register
Related
I have a project with a a library in a few directories. The cabal file is produced with hpack and looks ok. The project builds with cabal build and the main can be run with cabal run xx.
Using repl in vscode, I get occasionally
Could not load module ‘GIS.Subdivisions’
It is a member of the hidden package ‘CatCoreConcepts-0.2’.
Perhaps you need to add ‘CatCoreConcepts’ to the build-depends in your .cabal file.
The package is, of courese, listed in the dependencies. The error is not always occuring and I assume it is a probem with some data cached in the vscode Haskell HLS plugin. Is there a simple way to clean the cache of the plugin? Restart HLS and Developer: reload window in vscode is not having any effect.
I have had the problem where VSCode thinks modules are hidden. Many answers on SO, such as this one. Possible solution, which hopefully helps,
ghc-pkg expose CatCoreConcepts
This is not an answer to the main question, but to some OP comments.
I'd say cabal documentation is good (but lengthy).
A brief summary as I understand (not official documentation)
A Package is a set of components
A component is a set of modules (haskell files)
Module-name and file-name must be equal except for entrypoints (see below)
Components can be classified in two groups:
runnables: tests, benchmarks and executables
runnables must have a unique main function called the entrypoint
In the cabal file, you can use keywords executable, test-suite and benchmark for defining runnables
Within each runnable section in the cabal file there must be a field main-is pointing to the file with the entrypoint
The file-name of the entrypoint can be whatever but the module name must be Main.
Notice that runnable components can have multiple modules (haskell files). For example you can have a test suit consisting in a file with auxiliar functions and other file with the main function. Both files conform a component (a test-suite in this case)
non-runnables: libraries
In the cabal file, you can use keywords library for defining non-runnable component
For libraries you must specify the modules which are exposed with the exposed-modules keyword.
Runnable components can import non-runnable ones even if they are defined in the same package. But viceversa is not true.
As a good practice, each component should be separated in a different folder. Some libraries expect naming convention. For example: tests to be in a folder with the same name and with test_XXXX.hs format (this is regular across programing languages, not only Haskell)
When libraries are separated in folders the field hs-source-dirs must be specified to point to the folder with the haskell files
(the name runnable is not part of the official docs, but is the way I understand)
stack works pretty much the same as cabal since the former is just a different front-end for the later. So aside from different keywords and yaml format, all of the above can be applied to stack (notice that cabal updates more often than stack, therefore some features supported by cabal can be missing in stack.)
If you find this useful, I think I am opening an issue to the cabal docs to include it.
The Haskell project I am working on generates code(and tests for it) that is intended to be used as an independent Haskell library. I want to wrap it in a cabal project, so it can be included as a dependency.
I searched for a library interface for the cabal, so I can create a cabal project at a given directory by calling some functions, but found none.
I could, of course, just run bash commands from Haskell, but it looks ugly to me.
Is there any tool that will solve my problem in a nice way?
You want the Cabal package. You can parse an existing cabal file, change stuff in the data structures, and regenerate the text representation.
Edit in answer to comment:
I don't know of any tutorials. The links I gave are for the Haddock docs, and the mapping between data types and Cabal file text is pretty straightforward. So you should probably start by writing the code to produce a PackageDescription value and then call writePackageDescription on it.
Note the existence of emptyPackageDescription, which lets you just specify the fields you want.
(Removed link to pretty printer class because PackageDescription isn't a member.)
I am pretty new to Haskell as well as stack.
import Data.Set
import Data.Stack
The statements above trigger compilation error: Could not find module 'Data.Set'. Perhaps you meant 'Data.Int'. I tried to google and found nothing similar.
Hence, my question is: do I need to specify external dependencies manually or just my stack build command somewhy fails to grab appropriate modules from somewhat cache or repository?
In case I have to specify my dependencies manually, should I prefer .cabal or .yaml? What's the correct way to deal with versioning?
[Do] I need to specify external dependencies manually [...]?
Yes.
Since you are using Stack, it is easy to specify the dependent packages you import in your code. Depend on your Stack version, the default configuration might be a little bit different:
If you created your project with the latest version of Stack, you will see package.yaml in the root of your project (hpack is used in this case to specify the configurations). You need to add package dependencies there, e.g., containers for Data.Set. Here's an example of a dependencies section in one of my projects:
dependencies:
- base >= 4.7 && < 5
- containers
- time
- network
- bytestring
If you are using an older version of stack and do not see package.yaml, you need to edit your-project-name.cabal to add the dependencies. Here's the complete document telling you how to do it: https://docs.haskellstack.org/en/stable/GUIDE/#adding-dependencies
Personally, I prefer the new system with hpack (package.yaml). Basically, it is simpler, and it saves you time declaring all modules you have (not about dependency). If you have package.yaml, do not edit .cabal, which is automatically generated by hpack.
I am trying out the new linux packaging tool http://snapcraft.io/create/
It does have some documentation but it's not very mature and doesn't contain everything.
What I am trying to do is to generate a package for my binary that is compiled using Qt framework, thus it depends on a load of .so files. I couldn't find in documentation any way to convince snapcraft to pull all these dependencies and add them to the program hierarchy (the mounted squashfs).
So in order to "temporarily fix that" I hacked a very lame shell script that executes ldd on my binary and does this on its own. That "sort of" works because now indeed all the necessary libraries are in the image, but the program can't find them, because most of them have own paths and are not in root lib folder /usr/lib
The example of error I am getting when I try to start my program is:
/snap/huggle/x1/usr/bin/huggle: error while loading shared libraries: libGL.so.1: cannot open shared object file: No such file or directory
But the library is there:
/snap/huggle/x1/usr/lib/x86_64-linux-gnu/mesa/libGL.so.1
It just has no clue how to find it. On other hand, given that snapcraft is advertised as awesome simple stupid packaging tool, I find it quite weird that something so simple as packaging a C++ binary would be so complicated. How should I do this properly?
How do I find the source of the code I am importing. Like if I do
λ <Prelude>: import Graphics.EasyPlot
λ <Prelude Graphics.EasyPlot>:
How do I find that code. I do not mean an online copy of the code (Google is very good at indexing Hackage by that) but where it is on my system that I can edit. The reason is that it is a bit buggy, and I want to try and fix it. (I might submit a patch, but I just want to fix it for my own use first.)
As #ThomasDuBuisson mentioned, you many not necessarily find that on your system. One thing which I generally do is fetch it using cabal:
cabal fetch package-name
It downloads the tarballs of the package. Once you have fetched it, the entire source will be under the path where cabal puts it. In my case, it is (/home/sibi/.cabal/packages/hackage.haskell.org/package-name ). You can then untar and then build it from the cabal file which is already present there.
That being said you should probably using the version control system which the project is using as #bheklilr pointed out.