I have a Haskell library that I am developing using Stack. As I am developing the library, I like to write small test/experimentation programs that use the library. I keep a collection of these test programs for myself in a directory locally. These test modules are very quick and informal, and not appropriate to include as unit tests in the committed library code. Typically, most of them aren't even maintained and won't compile against the latest version of the library, but I keep them around in case I want to update them later. When I'm working on a test program, I want it to build against my working copy of the library, with any changes that I've made to the library locally.
How should I set up my Stack build environment for this situation? Here are some options I've tried, and the problems with each options.
Two Cabal packages, one Stack configuration. The stack.yaml file lists both packages and defines the build environment for both at once.
- Problem: The stack.yaml file needs to be included as part of the committed library source code, so that other developers can build the library from source reproducibly. I don't want the public stack.yaml file for my library to include build information for my local test projects.
- Problem: As far as I know, to make this work I need to have a .cabal file that lists all the executables and modules for my test programs. This is annoying to update whenever I want to throw together a quick experimental script, and will fail to build any of the test programs if I have even a single module that doesn't compile. I can't have a .cabal file with no sections, because Cabal gives "No executables, libraries,tests, or benchmarks found. Nothing to do.", and because this offers nowhere to list
build-depends
.
Create a Cabal sandbox for the test programs. Use
cabal sandbox add-source
to add the local library as a package. See also this answer.- Problem: Using Cabal sandboxes instead of Stack reintroduces a lot of the dependency problems that Stack is supposed to fix, such as using the system-global GHC instead of the GHC defined by the resolver.
Have a separate stack.yaml for the test programs. Add the library under
packages
aslocation: 'C:\Path\To\Local\Library'
and setextra-dep: true
for that dependency. (See here for more info on this feature.) Don't put any other Cabal packages underpackages
in the stack.yaml for the test programs. Usestack runghc
to invoke test programs within the scope of their stack.yaml.- Problem: I just can't get this one to work. Running
stack build
inside the test program directory gives "Error parsing targets: The project contains no local packages (packages not marked with 'extra-dep')". Runningstack runghc
acts as if no dependencies are present at all. I don't want to add a Cabal package for the test programs because this has the same problem as option 1 with needing to construct an explicit .cabal file describing the modules to build. - Problem: Stack build configuration info that I want to be identical between the library and the test programs has to be copied manually. For example, if I change the resolver in my library's stack.yaml, I also need to change it in the stack.yaml for my test programs separately.
- Problem: I just can't get this one to work. Running
Have a directory inside my working copy of the library that contains all of my test programs. Use
stack runghc
to invoke test programs in the context of the library.- Problem: I'd like the directory with my test programs to be outside of the directory containing my library source code and build configuration, so that I don't have to tell the version control for my library to ignore my test code, and can have my own local version control just for the test programs.
- Problem: Only works with a single local library dependency. If my test programs need to depend on local working copies of two different libraries with their own stack.yaml files, I'm out of luck.
Add a symbolic link inside my working copy of the library to a separate directory that contains all of my test programs. Navigate through the symlink and use
stack runghc
to invoke test programs in the context of the library.- Problem: Super awkward to use, especially since I'm on Windows and Windows has terrible symlink support.
- Problem: Still need to tell my version control system to ignore the symlink.
- Problem: Still only works with a single library dependency.