-
Notifications
You must be signed in to change notification settings - Fork 37
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Dev ghc session test #39
Dev ghc session test #39
Conversation
src/CabalHelper/Runtime/Main.hs
Outdated
@@ -70,6 +70,11 @@ import Distribution.Simple.LocalBuildInfo | |||
, withComponentsLBI | |||
, withLibLBI | |||
, withExeLBI | |||
|
|||
#if CH_MIN_VERSION_Cabal(2,0,0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CPP'ed import go at the end of the import list, grouped with the others.
src/CabalHelper/Runtime/Main.hs
Outdated
@@ -218,6 +238,7 @@ usage = do | |||
++" | ghc-lang-options [--with-inplace]\n" | |||
++" | package-db-stack\n" | |||
++" | entrypoints\n" | |||
++" | needsbuildoutput\n" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sed -i 's/needsbuildoutput/needs-build-output/g'
src/CabalHelper/Runtime/Main.hs
Outdated
libopts = | ||
-- AZ:TODO: we already have the clbi, use it rather |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
???
src/CabalHelper/Runtime/Main.hs
Outdated
in | ||
cleanRecursiveOpts (CLib lib) libbi libclbi | ||
-- ghcOptInputModules = toNubListR $ allLibModules lib clbi, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this comment convey any important information?
src/CabalHelper/Runtime/Main.hs
Outdated
, componentEntrypoints c)) | ||
return $ Map.fromList $ map snd includeDirs | ||
|
||
type SubDeps = ([UnitId], [FilePath], [(OpenUnitId, ModuleRenaming)], ChEntrypoint) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd prefer if this was a full blown datatype with record field names.
tests/GhcSession.hs
Outdated
@@ -30,9 +31,10 @@ main = do | |||
args <- getArgs | |||
topdir <- getCurrentDirectory | |||
res <- mapM (setup topdir test) $ case args of | |||
[] -> [ ("tests/exelib" , parseVer "1.10") | |||
[] -> [ | |||
("tests/exelib" , parseVer "1.10") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't change the indent style for no good reason please.
tests/GhcSession.hs
Outdated
exists <- doesDirectoryExist packageDir | ||
let opts' = if exists | ||
then ("-package-db " ++ packageDir) : "-Werror" : opts | ||
else "-Werror" : opts |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This whole packageDir
business shouldn absolutely not be here, if it has to be something in Main.hs is still broken. Remember this test is supposed to simulate what ghc-mod will have to do and the whole point of cabal-helper is to abstract away cabal specific hacks like that.
Can you explain why this is necessary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is a matter of timing.
If a component has ProduceBuildOutput
set, then invoking cabal build
(at the ghc-mod or higher level) will result in the packageDir
being created.
But at the point we invoke cabal-helper the build has not yet happened.
So one alternative is to invoke cabal-helper more than once, if ProduceBuildOutput
is set, and let it check for existence of that package db dir and add it to the options if needed.
But that does seem more complicated than requiring the cabal-helper client to do it.
@DanielG please give your preference.
tests/GhcSession.hs
Outdated
else "-Werror" : opts | ||
|
||
-- let opts' = "-Werror" : opts | ||
-- let opts' = "-v 3" : "-Werror" : opts |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dead code.
@@ -113,11 +132,15 @@ compileModule ep opts = do | |||
|
|||
handleSourceError (\e -> GHC.printException e >> return False) $ do | |||
|
|||
let target = case nb of | |||
ProduceBuildOutput -> HscNothing -- AZ: what should this be? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You know, I saw your conversation with ezyang and I didn't realize backpack packages with holes won't work with GHCi/HscInterpreted when we started this.
The way I see it we have two choices here either we tell ghc-mod which hscTarget it has to use and have it operate in a degraded capacity or we tell it to ignore such backpack packages altogether the latter would mean users couldn't even syntax check modules from such components.
The former would need investigating which target to use whereas the latter is more or less zero effort. I guess we can deduce that we need to change target/ignore a component based on needsBuildOutput
for now so we can defer the decision until we get to integrating these changes into ghc-mod.
combineEp (Just (ChLibEntrypoint es1 os1 ss1)) (ChLibEntrypoint es2 os2 ss2) = Just (ChLibEntrypoint (nub $ es2++es1) (nub $ os2++os1) (nub $ ss2++ss1)) | ||
combineEp (Just (ChLibEntrypoint es1 os1 ss1)) (ChExeEntrypoint mi os2) = Just (ChExeEntrypoint mi (nub $ os2++es1++os1++ss1)) | ||
combineEp (Just (ChExeEntrypoint _ os1)) (ChLibEntrypoint es2 os2 ss2) = Just (ChLibEntrypoint es2 (nub $ os2++os1) ss2) | ||
combineEp (Just (ChExeEntrypoint _ os1)) (ChExeEntrypoint mi os2) = Just (ChExeEntrypoint mi (nub $ os2++os1)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure what to make of this function. Half of it should really be a Semigroup
instance for ChEntrypoint
and the other half (the Maybe
) stuff is probably just mplus
or some such.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree it is messy, but have no good ideas on how to improve it. Working code alternatives welcomed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Something like this:
import Data.Semigroup
instance Semigroup ChEntrypoint where
ChLibEntrypoint es1 os1 ss1 <> ChLibEntrypoint es2 os2 ss2
= ChLibEntrypoint (nub $ es1 ++ es2) (nub $ os1 ++ os2) (nub $ ss1 ++ ss2)
-- etc.
combineEp Nothing ep = Just ep
combineEp maybeEp1 ep2 = (ep2 <>) <$> maybeEp1
I didn't check whether the order of the lists actually matters (I still don't understand the rest of the package well enough).
I think the Semigroup
instance can't be made much easier.
EDIT: Semigroup definition, Nothing
case
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking at this again I think a Semigroup instance just isn't appropriate here, it seems to me you're trying to use ChEntrypoint
as a container for intermediate data for which it is just not fit for. Especially the conversions between ChExe <-> ChLib
make this obvious and really don't fit what a Semigroup instance for this type should do in my mind (though it could probably be law abiding anyways). Previously I thought all the cases were just of the form ChXEntrypoint, ChXEntrypoint -> ChXEntrypoint
which is why I suggested Semigroup.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does recursiveIncludeDirs
really need to return a ChXEntrypoint
? It didn't need to previously, and if it doesn't need to, the function could be rewritten in a much simpler way using some sort of fold
I think. (Btw, in case of a successful Map.lookup u includeDirs
, the function returns an "accumulated" ChXEntrypoint
holding all the intermediate paths. Not sure whether this is intended.)
Still need clarity on best way of adding the local package db when it is needed and exists.
Which includes inserting the inplace directory for package includes
, ChEntrypoint) | ||
recursiveIncludeDirs includeDirs unit = go ([],[],Nothing) [unit] | ||
where | ||
go (afp,aci,Nothing ) [] = (afp,aci,error "recursiveIncludeDirs:no ChEntrypoint") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a lazy error, i.e. if you only inspect afp
and aci
, the error won't be thrown. I don't know whether this is the intended behaviour.
@@ -373,13 +398,33 @@ main = do | |||
return $ Just $ ChResponsePkgDbs $ map pkgDb $ withPackageDB lbi | |||
|
|||
"entrypoints":[] -> do | |||
#if CH_MIN_VERSION_Cabal(2,0,0) | |||
includeDirMap <- recursiveDepInfo lbi v distdir | |||
eps <- componentsMap lbi v distdir $ \c clbi _bi -> do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could remove the do
here since both cases are return
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, we can also pull the returns out of the two cases.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Except componentsMap
is in IO, so requires a return
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah you're right, but the two return
s can be merged into one like: return $ case ... of ....
since both cases just deal with pure values.
Tests now pass.
Please review