ghc-mod
ghc-mod copied to clipboard
GHC needs to be aware of FFI objects for projects using TemplateHaskell and some other extensions
ghc-mod throws an error after trying it on some file that uses foreign C++ function:
ByteCodeLink: can't find label
During interactive linking, GHCi couldn't find the following symbol: some_symbol_from_my_cpp_file
This may be due to you not asking GHCi to load extra object files,archives or DLLs needed by your current session. Restart GHCi, specifyingthe missing library using the -L/path/to/object/dir and -lmissinglibnameflags, or simply by naming the relevant files on the GHCi command line.
Alternatively, this link failure might indicate a bug in GHCi.If you suspect the latter, please send a bug report to: [email protected]
I have a C++ file listed in my cabal file under c-sources, it links correctly using either cabal-install or stack tools and my project builds fine and an interpreter (stach ghci and cabal repl) also starts without any problem. Also I have extra-libraries: stdc++ and ghc-options: -pgml g++ lines in there.
Can you give me like a minimal example project that still reproduces this bug?
If anyone else is having this issue, see https://github.com/eagletmt/ghcmod-vim/issues/19 for more information.
OK I figured out one cause of this bug: it is caused by the combination of foreign imports and {-# LANGUAGE TemplateHaskell #-}. Essentially if a module depends (possibly indirectly) on a module that imports foreign functions, and it uses {-# LANGUAGE TemplateHaskell #-}, then you will get this error.
A simple reproducible example is:
test.h
void test_fn();
test.c
#include "test.h"
#include <stdio.h>
void test_fn() {
printf("Hello World");
}
Lib.hs
{-# LANGUAGE TemplateHaskell #-}
module Lib.Lib
( testFn
) where
foreign import ccall "test_fn" c_test_fn :: IO ()
testFn :: IO ()
testFn = c_test_fn
Remove running ghc-mod check Lib.hs will cause the error, and it will go away if you remove {-# LANGUAGE TemplateHaskell #-}.
@WillSewell Have stumbled again upon this issue. Similar to your cause but with FlexibleInstances and ScopedTypeVariables pragmas instead. ghc-mod fails if both of them are present, but not with one at a time, while stack build requires both to complete. I'm building everything with stack and lts-6.12 at the moment.
@WillSewell I cannot reproduce this with GHC 8.0, what GHC version where you testing with?
Also I used the following as a cabal file.
name: template-haskell-ffi
version: 0.1.0.0
build-type: Simple
cabal-version: >=1.10
library
exposed-modules: Lib
other-extensions: TemplateHaskell
build-depends: base
default-language: Haskell2010
c-sources: test.c
Nontheless I can see just from inspecting the output of running ghc-mod with -g-v3 -vvv and comparing that to cabal repl -v2 that we're not passing any object files to GHC so obviously there will be symbols missing. The reason this only happens when TH is enabled is that we only switch GHC into real "GHCi" mode (aka HscInterpreted) when TH or a couple of other complex extensions are used in a given module graph (see https://github.com/DanielG/ghc-mod/blob/master/Language/Haskell/GhcMod/Target.hs#L493). When this mode isn't enabled we don't need any objects because we don't run the linker anyways.
There is actually a GHC ticket for the root cause of this problem which has some more details: https://ghc.haskell.org/trac/ghc/ticket/11425. Also https://github.com/DanielG/ghc-mod/issues/205
In lieu of a fix upstream an easy solution would be to just make GHC aware of these extra objects. This does however present the complication that the objects might need building initially. I think ghc-mod shouldn't go around directly running cabal build on a project so some better solution is needed for that case.
I actually though we were already picking up object files but looking at the GHC backend for Cabal: https://github.com/haskell/cabal/blob/master/Cabal/Distribution/Simple/GHC.hs#L526 these options are added in buildOrReplLib which calls componentGhcOptions, which is the function cabal-helper uses since it's the only way to construct GHC options without incurring an IO effect: https://github.com/DanielG/cabal-helper/blob/master/CabalHelper/Main.hs#L350.
I was using GHC 7.10.3.
That's great to have an answer on the root cause of this issue. Hopefully it's something that can be fixed properly in the future.