The community were inventive in their hacks to permit the testing of modules that belong to executable. The three most common solutions:
npm culture. Cabal would _(hopefully)_ never support that. Example: hdevtools.hs-source-dirs for executable and test-suite stanzas. Everything builds twice but you get to import the same modules as in executable. Kind of example: #3242.executable to a _(possibly internal)_ library and depend on this library from the test suite. Leave executable trivial. Example: pandoc.To my understanding, all three solutions listed above are not nice. A better solution that I can think of is to consider an executable stanza as a named, internal library for the purpose of referring to from a test suite with build-depends. The potentially problematic downside is that there may then be multiple, overlapping Main.main names to be imported, but this is easily solved with a combination of Cabal's main-is, ghc's -main-is and some naming discipline.
If consensus emerges, I can take it on myself to offer a patch as a summer project.
What's so bad about the 3rd option,
executable to a _(possibly internal)_ library and depend on this library from the test suite. Leave executable trivial. I have done this quite often myself in projects, and tbh, I don't see what's so inconvenient about it. It's easy to understand as it uses obvious & explicit constructs/verbs.
What you suggest sounds to me a bit too magical and non-obvious (as e.g. it'd blur the distinction between exposed-modules and other-modules; and there'd be an exception where build-depends refers to executable components rather than library components), and would add implementation complexity (which directly translates into maintenance cost).
So I'm afraid I have to say I don't think this is a good idea.
@hvr I do not understand the details you bring up:
exposed-modules and other-modules?build-depends refers to executable components rather than library components?Can you help me see the problem?
Without also having the same understanding as @hvr, I think it would be nice and user friendly to be able to reference executable projects as libraries. Shifting UI related logic out of the UI project and adding an entire other library sounds tedious and annoying. The manuever of including the executable path in hs-source-dirs adds redundancy to the cabal file because it needs the dependencies twice.
To establish some precedent, .NET allows you to reference executables in your solution and use them as if they were libraries. This is personally one of the things I expected to just work.
How the OP proposal is different than simply using Cabal's internal libraries?
I agree with @phadej and @hvr. Just use internal libraries, this exactly what they are for.
@23Skidoo @hvr @phadej So what is the point of having an executable stanza if the code therein best be as trivial as possible? This is clearly not in any way different than having an internal library with a pointer to the main function, while encouraging practices that are not the best.
It looks to me as though you are defending the status quo by means of your authority and a priori consensus, rather than logical argument. The reasons given by Herbert are exposed too concisely to be easy to grasp _(I asked for a clarification, but none was given)_, but the parts I can understand relate to implementation details and inertia, which are both unrelated to design itself. The other two of you did not put forward any arguments at all. So, it appears to me as though you are not admitting that there is a problem, and this is why I re-stated it in the first lines of this post. I appreciate if you would take a moment to actually address it.
So, let me state the problem again, in the clearest way I could.
A best practice concerning testing projects is to move as much code as possible to a library, leaving the executable trivial.
In this we have consensus, as expressed in the response of Herbert.
The detailed motivation for this best practice is in the following syllogism:
Driven to the extreme, this approach gets us to an executable so trivial that it is isomorphic to a pointer to the actual code located in a library: main = Library.main. Some projects we may observe in the wild approach this ideal very closely. _(pandoc, haddock, doctest — by any measure, prominent projects.)_
The current arrangement of Cabal stanzas does not even hint to this best practice.
Quite the opposite, the intuitive way when making an _executable_ is to use the executable stanza!
Therefore:
executable stanza does not serve any real purpose other than providing a needlessly customizable pointer.executable stanza is misleading and promotes practices that are contrary to the best.I also offered a solution, that I think is obvious and nice: make executable a special case of an internal library with a pointer to main. Maybe this solution is problematic in some way. That does not cancel the problem.
The pool of maintainers is not some universal constant. If we design a great tool, more people will want to lend a hand in development, and the maintenance cost would be divided. If we choose to fence off and be obscure, less people will come to help, and it will be harder to actually find time to improve things. From this, it follows that the argument to maintenance cost, given by Herbert, is based on a pessimistic assumption that may not be correct. If the majority of maintainers choose to be pessimistic, just say so, and I will not bother you further.
Most helpful comment
What's so bad about the 3rd option,
executableto a _(possibly internal)_libraryand depend on this library from the test suite. Leaveexecutabletrivial.I have done this quite often myself in projects, and tbh, I don't see what's so inconvenient about it. It's easy to understand as it uses obvious & explicit constructs/verbs.
What you suggest sounds to me a bit too magical and non-obvious (as e.g. it'd blur the distinction between
exposed-modulesandother-modules; and there'd be an exception wherebuild-dependsrefers toexecutablecomponents rather thanlibrarycomponents), and would add implementation complexity (which directly translates into maintenance cost).So I'm afraid I have to say I don't think this is a good idea.