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

Support for Windows — replacing autoconf with Setup.hs #30

Merged
merged 5 commits into from
Sep 10, 2015

Conversation

mwu-tow
Copy link
Contributor

@mwu-tow mwu-tow commented Sep 8, 2015

Summary of changes

Removed the dependency on autotools that causes problems on Windows (as discussed in #25). The functionality from configure.ac (detecting CUDA Toolkit and passing additional flags to ghc) was implemented in Setup.hs. User can now override results of Setup.hs configure step by providing custom cuda.buildinfo file.

Thanks to that, the package neatly installs on Windows machines with CUDA without requiring additional dependencies, special environment nor restricting the possible CUDA locations (paths with spaces just work).

The package should install as before on Linux and OSX machines, though some more testing (particularly on OSX) would be welcome.

Because the extraGHCiLibs support was introduced in Cabal 1.22, that version is needed to compile the package.

Changes in detail

What's changed

Old behaviour:

Setup.hs executed the configure script that yielded cuda.buildinfo file (being essentially a map of flags). Setup.hs used then that file to perform build.

New behaviour:

Setup.hs looks for CUDA Toolkit and based upon its location and current platform generates file cuda.buildinfo.generated. Then, as before, the file is used when performing build.

In case when something goes wrong (or just to ease experimenting) user can provide a custom cuda.buildinfo file. If it is present, it will be prefered over the generated one.

Other differences

I removed options for C2HS that set nvcc as the C preprocessor. It is impossible to use it on Windows, however using MinGW's gcc seems to work just fine. If it works on Windows, all the more it should work on Linux. So to avoid unnecessery differences between platforms, I've removed nvcc from its role as preprocessor for C2HS everywhere.

Even though I tried to provide all the needed logic in Setup.hs it is not necessarily the same as the old configure.ac. For example, it does not check whether cuda and cudart actually do export functions we expect. Implementing this in Haskell seemed troublesome and I didn't think it is worth of benefit.
I'd say it is rather the Cabal library that should provide such methods as part of their configuration utilities.

I was forced to bump the required cabal library to 1.22 due to extra-ghci-libraries support being added in that version. This option is needed on Windows to avoid the need to rename the CUDA Toolkit dlls (as they don't match filenames of their respective .lib import libraries). I believe it should be possible to work around this requirement, yet it was not worth the effort needed.

How does it work

CUDA Toolkit detection iterates over candidate locations and takes the first one looking like CUDA Toolkit. The candidate locations are currently:

  • CUDA_PATH environment variable (it is set by the CUDA installer on Windows)
  • going two directories up over the nvcc executable location from PATH
  • /usr/local/cuda

The location is considered valid when it contains include/cuda.h file. In future that validation rule may be refined. When CUDA Toolkit cannot be find, configure step fails. Setup.hs outputs the checked locations and reason why were they rejected, so it should be pretty obvious what is going on.

Flags added on all patforms:

  • cc-options: include and library directory from cuda toolkit
  • ld-options: additional libraries to link against: cuda, cudart
  • flags for c2hs to pass to the cpp: -m32/-m64 depending on architecture, -DUSE_EMPTY_CASE when on GHC version >= 7.8, -E

Windows-only flags:

  • extra-ghci-libraries with names of DLL paired with cuda and cudart

OSX-only flags

  • special frameworks: CUDA entry
  • ld-options: -F/Library/Frameworks
  • flag for c2hs to pass to cpp: -U__BLOCKS__ when /usr/include/stdlib.h contains __BLOCKS__ substring

Other notes

I tried to follow the behaviour of configure.ac. However, as I observed, some of the flags that are set, are not needed for me to compile:

  • ghc-options (the one that takes options for cc and ld with -optc and -optl prefix) does not seem to be needed

I have done tests on computers in my company. They likely have CUDA installed in an uniform way, so help in testing in different environment would be welcome. On Windows machines my version works. On Linux machines both old and proposed version of setup work. On a single Mac machine with CUDA I was able to obtain, neither did work — it needed to be run with /usr/local/cuda/lib being passed as --extra-lib-dirs. When it is passed, both current and my version work.

In my tests on OSX I haven't observed any difference whether framework is defined or not along with is path -F/Library/Frameworks. I have left it, as I have no idea why it was needed but I'd be happy to know whether it can be safely removed or not.

To sum up: my version works on all machines when current configure.ac worked. It additionally works on Windows. I'd be great to have it tested in other environment — if there are any issues with the new Setup.hs I'd be happy to fix them, or provide you needed help.

…o Setup.hs. This resolves issues with installing the package on Windows.
@tmcdonell
Copy link
Owner

This is great!! Thanks for the very comprehensive summary of changes as well. I'll test this out on a Mac or two here as you suggest, but otherwise it looks like you have tested pretty well already and it looks fine.

@mwu-tow
Copy link
Contributor Author

mwu-tow commented Sep 9, 2015

I pushed a few more commits based on Travis outputs. I got the checks to pass by updating cabal and cabal-install. The only one failing is the GHC-head one (that cannot update cabal-install) — I'm not sure how to fix it, but it was failing anyway so I'll leave it for later.

That'd be all from my side, I have no plans for further changes now — unless new issues are found.

@tmcdonell
Copy link
Owner

Out of curiosity... I noticed that you had a separate 'windows' branch which shows the development history. I would have been happy to accept the pull request directly from there (preferred, even). Any reason you chose to squash the commits? (maybe these branches are actually different attempts, I didn't look in detail.)

@tmcdonell tmcdonell merged commit 6366227 into tmcdonell:master Sep 10, 2015
@mwu-tow
Copy link
Contributor Author

mwu-tow commented Sep 10, 2015

Indeed, this branch was squashed version of windows. I did it because the windows is full "dirty" commits that I made to track my development, not because they make sense. Some had intentional errors to check the error handling, there were some experiments appearing and disappearing, as I tweaked things, looking for the most satisfactory solution.
Practically all commits there are broken in one way or another (i.e. don't work on some platforms) and I didn't see reason why anyone would want to return to them. Well, perhaps git-blaming the Setup.hs for rationale… But all the needed info is in the comments anyway I think.
(Still, I could've replaced this squashed version with original branch history if you'd say so.)

@tmcdonell
Copy link
Owner

No it's fine, I was just curious and thought I would ask. I guess it makes sense to squash it as you did since they are mostly work-in-progress commits, but I wouldn't have minded.

I have merged the changes. I will upload the new version to Hackage shortly.

Thanks again for this monumental effort! Really great work!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants