Skip to content
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

Explicitly support building with -fno-code #1176

Open
nh2 opened this issue Jan 11, 2013 · 27 comments
Open

Explicitly support building with -fno-code #1176

nh2 opened this issue Jan 11, 2013 · 27 comments

Comments

@nh2
Copy link
Member

nh2 commented Jan 11, 2013

Summary by @ezyang. There is no way to ask Setup to just typecheck a package. It sort of works if you pass -fno-code via --ghc-options but that's purely accidental.


I use cabal build --ghc-options="-Wall -fno-code" to quickly get all errors/warnings from a project and show them in an editor.

However, when I have something like this

executable Shared.so
  hs-source-dirs:
    apps
  main-is:
    Shared.hs
  build-depends:
      base >= 4 && <= 5
  ghc-options:
    -optl-shared -optc-DMODULE=Shared -no-hs-main -fPIC -shared -dynamic
  cc-options: -DMODULE=Shared -shared
  ld-options: -shared /home/niklas/opt/haskell-7.4/lib/ghc-7.4.2/libHSrts-ghc7.4.2.so

in my cabal file that only builds a shared object, I get:

Warning: the following files would be used as linker inputs, but linking is not being done: dist/build/...
ghc: no input files
Usage: For basic information, try the `--help' option.

Should we get this warning although we explicitly said -fno-code?

If yes, can we add an option to disable this kind of warning so that it does not clutter the warnings I am actually interested in (to show in the editor)?


Update:

(The original title was Add option to disable non-linking warnings with -fno-code.)

I just realized that there is an actual bug in this:

After the warning, due to the ghc error cabal will just stop and build no further. This should not happen as there is no code to build!

@nh2
Copy link
Member Author

nh2 commented Jan 13, 2013

This even happens when you don't have a configuration as above, but a way more normal one, like hspec's cabal file.

A normal build looks like this:

Building hspec-1.4.3...                                                                     
Preprocessing library hspec-1.4.3...
[ 1 of 14] Compiling Test.Hspec.Compat ( src/Test/Hspec/Compat.hs, dist/build/Test/Hspec/Compat.o )
...
[14 of 14] Compiling Test.Hspec.QuickCheck ( src/Test/Hspec/QuickCheck.hs, dist/build/Test/Hspec/QuickCheck.o )
In-place registering hspec-1.4.3...
Preprocessing executable 'hspec-discover' for hspec-1.4.3...
[1 of 2] Compiling Run              ( hspec-discover/src/Run.hs, dist/build/hspec-discover/hspec-discover-tmp/Run.o )
[2 of 2] Compiling Main             ( hspec-discover/src/Main.hs, dist/build/hspec-discover/hspec-discover-tmp/Main.o )
Linking dist/build/hspec-discover/hspec-discover ...

But cabal build --ghc-options="-fno-code" gives:

Building hspec-1.4.3...                                                
Preprocessing library hspec-1.4.3...
[ 1 of 14] Compiling Test.Hspec.Compat ( src/Test/Hspec/Compat.hs, nothing )
...
[14 of 14] Compiling Test.Hspec.QuickCheck ( src/Test/Hspec/QuickCheck.hs, nothing )
/usr/bin/ar: dist/build/Test/Hspec.o: No such file or directory

Note this only breaks if the code hasn't been built yet (e.g. after cabal clean). If it has been built before, cabal build --ghc-options="-fforce-recomp -fno-code" correctly yields:

Building hspec-1.4.3...
Preprocessing library hspec-1.4.3...
[ 1 of 14] Compiling Test.Hspec.Compat ( src/Test/Hspec/Compat.hs, nothing )
...
[14 of 14] Compiling Test.Hspec.QuickCheck ( src/Test/Hspec/QuickCheck.hs, nothing )
In-place registering hspec-1.4.3...
Preprocessing executable 'hspec-discover' for hspec-1.4.3...
[1 of 2] Compiling Run              ( hspec-discover/src/Run.hs, nothing )
[2 of 2] Compiling Main             ( hspec-discover/src/Main.hs, nothing )

I think this is a bug - cabal build --ghc-options="-fno-code" should always work, no matter if code had been generated before!

@nh2
Copy link
Member Author

nh2 commented Jan 13, 2013

@23Skidoo Can you reproduce this with some of your packages (or hspec as above)?

@23Skidoo
Copy link
Member

@nh2 I'm a bit swamped right now, will look at this later.

@nh2
Copy link
Member Author

nh2 commented Jan 13, 2013

I was thinking into this direction (nh2@0c51929) but then realized that what I want is not that easy: You could perform a "read-only" typecheck with cabal to build the library, but as soon as you want to typecheck an executable (that depends on your own library and is in a different directory to avoid repeated compilation), you actually need the result of the library compilation.

Actually, you only need the *.hi files; it should be possible to generate them without further code generation, but I don't know how (see http://stackoverflow.com/questions/14306934/haskell-how-to-only-generate-hi-file-with-ghc).

@nh2
Copy link
Member Author

nh2 commented Jan 13, 2013

In the mean time, an easy work around would be #1177 - making a full cabal build instant by skipping linking if not necessary. (This could also be accomplished with -c, but that still performs unnecessary registering and unnecessarily links .so files.) On success (otherwise we have an error anyway), we can immediately run cabal build --ghc-options="-fforce-recomp -Wall -fno-code" which will work now since all necesssary files already exist.

However, this doesn't work as described in my original bug report: ghc reports ghc: no input files and terminates before the remaining warnings can be generated.

@nh2
Copy link
Member Author

nh2 commented Jan 13, 2013

https://github.com/nh2/cabal/compare/no-code-link-shared is a proposal to skip linking on -fno-code. It fixes the error described.

An explicit cabal option to disable this step might be better, though.

@ezyang
Copy link
Contributor

ezyang commented Jun 27, 2014

I just added an option -fwrite-interface, to dump interface files precisely when you want to do something like typecheck a library, and then typecheck a dependent executable.

@nh2
Copy link
Member Author

nh2 commented Jul 15, 2014

@ezyang Can you explain a bit more how this is intended to be used?

@ezyang
Copy link
Contributor

ezyang commented Jul 15, 2014

If you are planning on doing only typechecking cycles, and you have a library + executable Cabal file, run -fno-code and -fwrite-interface to typecheck the library, and then you will be able to type check the executable (because the library hi files are available.) Needs some UI polish, obviously!

@asivitz
Copy link

asivitz commented Sep 4, 2014

I also see this error when building even static libraries or executables. Would be happy to hack on it if that's helpful, although I haven't looked at cabal's code before. Not sure if this is a beginner-level problem or not.

@alilleybrinker
Copy link

This issue seems to persist, and is currently causing minor frustration in using SublimeHaskell, whose default build mechanism uses two builds: first a standard cabal build and then cabal build -v0 --ghc-options="-fforce-recomp -Wall -fno-code" to gather warnings. This issue is causing SublimeHaskell to display a bothersome error pane every time a project is recompiled (which happens every save). It's a minor issue, but a fix would be appreciated.

Here is the relevant SublimeHaskell issue: SublimeHaskell/SublimeHaskell#158

@ttuegel ttuegel added this to the Cabal-1.24 milestone Apr 23, 2015
@23Skidoo 23Skidoo modified the milestones: Cabal 1.24, Cabal 1.26 Feb 21, 2016
@ezyang ezyang modified the milestone: Cabal 2.0 Sep 6, 2016
@ezyang ezyang changed the title Cabal error when building with -fno-code Explicitly support building with -fno-code Sep 8, 2016
@ezyang ezyang self-assigned this Sep 8, 2016
@ezyang ezyang added this to the 2.0 milestone Sep 8, 2016
@ezyang ezyang modified the milestones: , 2.0 Sep 21, 2016
@nh2
Copy link
Member Author

nh2 commented Nov 12, 2016

A tip from @rwbarton just now on #ghc, we could use -e which is like ghci, but terminates.

TH works in ghci (due to use of bytecode), so this should be almost as fast as -fno-code (it still generates the bytecode which is some code, but in my experience that's much faster than even -O0).

@mightybyte
Copy link
Collaborator

I'd like to add another vote for this ticket. I'm not sure what the UI should be (cabal typecheck or cabal build --typecheck come to mind). Whether it's called "typecheck", "no-code", "fast", etc is not a huge issue (although "no-code" never seemed very intuitive to me personally). The important thing in my mind is to have this as an explicit cabal option somewhere so the fastest compile loop is more discoverable.

@sboosali
Copy link
Collaborator

the -e option doesn't work for me, because I'm using cabal build as a replacement for ghci in a project where the interpreter can't load at all because of linking errors (i.e. and thus cabal repl, ghcid, dante, etc can't help).

@andreasabel
Copy link
Member

In v1-cabal, this works for just type-checking:

cabal v1-build --builddir=dist-no-code \
	  --ghc-options=-fno-code \
	  --ghc-options=-fwrite-interface

In v2-cabal, it seems that passing new --ghc-options will cause ALL THE DEPENDENCIES to be rebuilt. That defeats the purpose of quick type-checking.

Example: We build ordinarily:

$ cabal v2-build -w ghc-8.0.2
Resolving dependencies...
Build profile: -w ghc-8.0.2 -O1
In order, the following will be built (use -v for more details):
 - haskell-lexer-1.1 (lib:haskell-lexer) (requires build)
 - prettyprinter-1.7.0 (lib) (requires build)
 - pretty-show-1.10 (lib) (requires build)
 - prettyprinter-ansi-terminal-1.1.2 (lib) (requires build)
 - BNFC3-3.0 (lib) (configuration changed)
 - BNFC3-3.0 (exe:bnfc3) (configuration changed)
...

After that, we want to just type-check:

$ cabal v2-build -w ghc-8.0.2 --ghc-options=-fno-code --ghc-options=-fwrite-interface
Resolving dependencies...
Build profile: -w ghc-8.0.2 -O1
In order, the following will be built (use -v for more details):
 - base-orphans-0.8.4 (lib) (requires build)
 - clock-0.8.2 (lib) (requires build)
 - colour-2.3.5 (lib) (requires build)
 - containers-0.6.4.1 (lib) (requires build)
 - haskell-lexer-1.1 (lib:haskell-lexer) (requires build)
 - alex-3.2.6 (exe:alex) (requires build)
 - microlens-0.4.12.0 (lib) (requires build)
 - mtl-2.2.2 (lib) (requires build)
 - stm-2.5.0.0 (lib) (requires build)
 - string-qq-0.0.4 (lib) (requires build)
 - transformers-compat-0.6.6 (lib) (requires build)
 - extra-1.7.9 (lib) (requires build)
 - ansi-terminal-0.11 (lib) (requires build)
 - th-abstraction-0.4.2.0 (lib) (requires build)
 - binary-0.8.8.0 (lib) (requires build)
 - happy-1.20.0 (exe:happy) (requires build)
 - transformers-base-0.4.5.2 (lib) (requires build)
 - microlens-mtl-0.2.0.1 (lib) (requires build)
 - ansi-wl-pprint-0.6.9 (lib) (requires build)
 - microlens-th-0.4.3.9 (lib) (requires build)
 - text-1.2.4.1 (lib) (requires build)
 - monad-control-1.0.2.3 (lib:monad-control) (requires build)
 - optparse-applicative-0.16.1.0 (lib) (requires build)
 - prettyprinter-1.7.0 (lib) (requires build)
 - pretty-show-1.10 (lib) (requires build)
 - prettyprinter-ansi-terminal-1.1.2 (lib) (requires build)
 - BNFC3-3.0 (lib) (configuration changed)
 - BNFC3-3.0 (exe:bnfc3) (configuration changed)

^C is the only answer to such madness!

@fgaz
Copy link
Member

fgaz commented Aug 28, 2021

@andreasabel I think the issue you mention is #3579: ghc-options is not available in top-level local options (but it still is in per-package options)

@jneira
Copy link
Member

jneira commented May 1, 2022

The command toonly typecheck suggested by @andreasabel:
cabal v2-build --ghc-options=-fno-code --ghc-options=-fwrite-interface

is more useful after #7973, cause now ghc-options applies only to all local packages. So change it does not trigger the recompilation of dependencies (aka remote packages).

@nh2 would be it enough for your use case? how could be it improved to fit it? create a new command would be difficult to get done

@kindaro
Copy link

kindaro commented Jul 10, 2022

This is a long awaited improvement. I built a shiny new Cabal executable and tried it out today.

+

It works for a single component:
% ~/.cabal/bin/cabal init --non-interactive
Warning: this is a debug build with assertions enabled.
[Log] Guessing dependencies...
[Log] Using cabal specification: 3.6
[Warning] unknown license type, you must put a copy in LICENSE yourself.
[Log] Creating fresh file CHANGELOG.md...
[Log] Creating fresh directory ./app...
[Log] Creating fresh file app/Main.hs...
[Log] Creating fresh file x.cabal...
[Warning] No synopsis given. You should edit the .cabal file and add one.
[Info] You may want to edit the .cabal file and add a Description field.

% ~/.cabal/bin/cabal build --ghc-options=-fno-code --ghc-options=-fwrite-interface
Warning: this is a debug build with assertions enabled.
Resolving dependencies...
Build profile: -w ghc-8.10.7 -O1
In order, the following will be built (use -v for more details):
 - x-0.1.0.0 (exe:x) (first run)
Warning: this is a debug build with assertions enabled.
Configuring executable 'x' for x-0.1.0.0..
Warning: this is a debug build with assertions enabled.
Preprocessing executable 'x' for x-0.1.0.0..
Building executable 'x' for x-0.1.0.0..
[1 of 1] Compiling Main             ( app/Main.hs, nothing )
% echo $?
0

It does not work when there are multiple interdependent components:
% ~/.cabal/bin/cabal init --non-interactive --libandexe
Warning: this is a debug build with assertions enabled.
[Log] Guessing dependencies...
[Log] Guessing dependencies...
[Log] Using cabal specification: 3.6
[Warning] unknown license type, you must put a copy in LICENSE yourself.
[Log] Creating fresh file CHANGELOG.md...
[Log] Creating fresh directory ./src...
[Log] Creating fresh file src/MyLib.hs...
[Log] Creating fresh directory ./app...
[Log] Creating fresh file app/Main.hs...
[Log] Creating fresh file x.cabal...
[Warning] No synopsis given. You should edit the .cabal file and add one.
[Info] You may want to edit the .cabal file and add a Description field.

% ~/.cabal/bin/cabal build --ghc-options=-fno-code --ghc-options=-fwrite-interface
Warning: this is a debug build with assertions enabled.
Resolving dependencies...
Build profile: -w ghc-8.10.7 -O1
In order, the following will be built (use -v for more details):
 - x-0.1.0.0 (lib) (first run)
 - x-0.1.0.0 (exe:x) (first run)
Warning: this is a debug build with assertions enabled.
Configuring library for x-0.1.0.0..
Warning: this is a debug build with assertions enabled.
Preprocessing library for x-0.1.0.0..
Building library for x-0.1.0.0..
[1 of 1] Compiling MyLib            ( src/MyLib.hs, nothing, /tmp/x/dist-newstyle/build/x86_64-linux/ghc-8.10.7/x-0.1.0.0/build/MyLib.dyn_o )
/usr/bin/ar: dist-newstyle/build/x86_64-linux/ghc-8.10.7/x-0.1.0.0/build/MyLib.o: No such file or directory
Error: cabal: Failed to build x-0.1.0.0 (which is required by exe:x from
x-0.1.0.0).

% echo $?
1

It seems that Cabal tries to link the dependent components (such as internal libraries), but there is nothing to link because nothing was built!

 

I cannot wait for this improvement to be released!

@kindaro
Copy link

kindaro commented Jul 10, 2022

If adding a new command cabal typecheck (or a special flag cabal build --typecheck) is still on the table, I say it should behave like this:

  • Accept the same options as cabal build. (So that the one can be easily swapped for the other.)
  • Produce the same standard error as cabal build. (So that it calls out all errors.)
  • Produce no object files.
  • Run faster.

Even though thanks to haskell-language-server one needs to call Cabal only rarely, it is still a good sanity check for when one is about to commit some code, for continuous integration or whenever haskell-language-server gets stuck or cannot start.

@andreasabel
Copy link
Member

Yes, it should be like -O0, in particular, use its own build directory.
The main annoyance with the current workaround (a separate cabal.project file with suitable ghc-options) is that builddir isn't accepted in cabal.project, and has to be passed on the command line manually all the time, like in https://github.com/agda/agda/blob/a47f8762978e878ecf6ed6081fa3772acc3499d1/Makefile#L238 .
In contrast -O0 stores build artefacts in its own .../noopt/... folders so that the regular build artefacts (-O1) are not overwritten.

@ulysses4ever
Copy link
Collaborator

@andreasabel sorry for a basic question, but why do you need to store -no-code artifacts separately? For -O0, a separate directory is needed so that you don't rebuild every time you switch configuration, but that shouldn't apply to -no-code as it shouldn't, in theory, generate any different artifacts?

@andreasabel
Copy link
Member

it shouldn't, in theory, generate any different artifacts?

The typechecking-only build tree contains the cabal configuration, interface files, and even some object files (e.g. Paths_*.o, setup/Main.o, modules using TemplateHaskell). Until evidence to the contrary is produced, I must assume there are differences.

@ulysses4ever
Copy link
Collaborator

@Mikolaj you added this issue to the project about replacing v1-commands, but I don't quite see which v1 functionality this would replace. At least, I don't think there's anything better in v1 than already shown here --no-code, which works perfectly with v2. The issue is about wrapping it into a prettier interface, but that's unrelated to v1 I think?

So, how about we remove this from the project?

@Mikolaj
Copy link
Member

Mikolaj commented Jul 11, 2023

Yes, I guess the workaround is good enough not to make this issue a blocker (though probably not to close the issue and, in any case, that's for the affected users to opine on). Let me remove this ticket from the https://github.com/haskell/cabal/projects/12 project. Thanks.

@andreabedini andreabedini added the old-milestone: ⊥ Moved from https://github.com/haskell/cabal/milestone/5 label Oct 17, 2023
@ulysses4ever ulysses4ever added re: v1-vs-v2 and removed old-milestone: ⊥ Moved from https://github.com/haskell/cabal/milestone/5 labels Nov 14, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests