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

Add --dynlibdir #3979

Merged
merged 1 commit into from
Oct 20, 2016
Merged

Add --dynlibdir #3979

merged 1 commit into from
Oct 20, 2016

Conversation

christiaanb
Copy link
Collaborator

--dynlibdir indicates the directory in which dynamic libraries
are installed. By default this setting is equal to:

$libdir/$abi

The static libraries will still end up in:

$libdir/$libsubdir

With $libsubdir/$abi as the default directory for dynamic
libraries, dynamic libraries will by default end up in a
single shared directory (per package database). This has the
potential to reduce start-up times for dynamically linked
executable as only one RPATH per package database will be
needed.

@mention-bot
Copy link

@christiaanb, thanks for your PR! By analyzing the history of the files in this pull request, we identified @ezyang, @23Skidoo and @dcoutts to be potential reviewers.

@bgamari
Copy link
Contributor

bgamari commented Oct 13, 2016

Thanks @christiaanb!

Copy link
Member

@23Skidoo 23Skidoo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good modulo minor comments.

import Distribution.Text
import qualified Distribution.Compat.Graph as Graph

import Data.List (stripPrefix)
import System.FilePath
import qualified Data.Map as Map

import System.Directory (doesDirectoryExist, canonicalizePath)
import System.Directory (doesDirectoryExist, canonicalizePath, getDirectoryContents)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Formatting seems off.

@@ -273,6 +274,19 @@ depLibraryPaths inplace relative lbi clbi = do

allDepLibDirs' = internalLibs ++ allDepLibDirs
allDepLibDirsC <- traverse canonicalizePathNoFail allDepLibDirs'
-- Only get the directories that contain dynamic libraries
let soExtension = case buildOS of
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use dllExtension from D.S.BuildPaths here.

@ilovezfs
Copy link
Collaborator

@christiaanb Will there be a Sierra solution for the static libraries too?

@christiaanb
Copy link
Collaborator Author

@ilovezfs There is a problem with static libraries on Sierra????

@ilovezfs
Copy link
Collaborator

Probably not ... just trying to get git-annex to build in a cabal sandbox using this PR and still getting stuck at yesod-auth, but I'm probably doing something wrong.

@christiaanb
Copy link
Collaborator Author

Closing this PR, as it lead to problems with RPATH calculations in GHC. The definitive solution for https://ghc.haskell.org/trac/ghc/ticket/12479 should be #3982. I'm terribly sorry that it took 3 PRs to fix this.

@23Skidoo
Copy link
Member

I'm terribly sorry that it took 3 PRs to fix this.

Oh, you shouldn't be. We are all very grateful to you for working so hard on this.

@@ -266,24 +268,37 @@ depLibraryPaths inplace relative lbi clbi = do
-}
getLibDir sub_clbi
| inplace = componentBuildDir lbi sub_clbi
| otherwise = libdir (absoluteComponentInstallDirs pkgDescr lbi (componentUnitId sub_clbi) NoCopyDest)
| otherwise = dynlibdir (absoluteComponentInstallDirs pkgDescr lbi (componentUnitId sub_clbi) NoCopyDest)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't get this bit.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll need to resolve this.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, that entire function is there to find the locations of dynamic libraries. Since libdir now only contains the location of static libraries, we should use dynlibdir.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep ok

@dcoutts
Copy link
Contributor

dcoutts commented Oct 18, 2016

So we're planning to resurrect this approach and make ghc do the right thing.

See https://phabricator.haskell.org/D2611

@dcoutts dcoutts reopened this Oct 18, 2016
Copy link
Contributor

@dcoutts dcoutts left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not that much to do to get this working with the new approach based on using dynamic-library-dirs.

then libdir installDirs : extraLibDirs bi
else extraLibDirs bi,
then libdir installDirs :
dynlibdir installDirs : extraLibDirs bi
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This bit will need to be extended to set the libraryDynDirs if that's supported by the target compiler, and otherwise put both libdir and dynlibdir in the libraryDirs as the patch does now.

@@ -779,18 +779,20 @@ tests config = do
uid = componentUnitId (targetCLBI target)
dir = libdir (absoluteComponentInstallDirs pkg_descr lbi uid
NoCopyDest)
dyndir = dynlibdir (absoluteComponentInstallDirs pkg_descr lbi
uid NoCopyDest)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should share this better, e.g.

InstallDirs{libdir,dynlibdir} = absoluteComponentInstallDirs pkg_descr lbi uid NoCopyDest

internalLibsC <- traverse canonicalizePathNoFail internalLibs

let allDepLibDirs' = internalLibsC ++ allDepLibDirsC
p = prefix installDirs
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So all this stuff can be reverted.

@@ -266,24 +268,37 @@ depLibraryPaths inplace relative lbi clbi = do
-}
getLibDir sub_clbi
| inplace = componentBuildDir lbi sub_clbi
| otherwise = libdir (absoluteComponentInstallDirs pkgDescr lbi (componentUnitId sub_clbi) NoCopyDest)
| otherwise = dynlibdir (absoluteComponentInstallDirs pkgDescr lbi (componentUnitId sub_clbi) NoCopyDest)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll need to resolve this.

@dcoutts
Copy link
Contributor

dcoutts commented Oct 18, 2016

Other dynamic-library-dirs changes in https://github.com/dcoutts/cabal/tree/osx-dyn-linking-hackery branch

Copy link
Contributor

@dcoutts dcoutts left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is looking really good.

@@ -266,24 +268,37 @@ depLibraryPaths inplace relative lbi clbi = do
-}
getLibDir sub_clbi
| inplace = componentBuildDir lbi sub_clbi
| otherwise = libdir (absoluteComponentInstallDirs pkgDescr lbi (componentUnitId sub_clbi) NoCopyDest)
| otherwise = dynlibdir (absoluteComponentInstallDirs pkgDescr lbi (componentUnitId sub_clbi) NoCopyDest)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep ok

comp = compiler lbi
supportsLibraryDynDir = case compilerFlavor comp of
GHC -> compilerVersion comp > mkVersion [8,0,1]
_ -> False
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We now try to avoid sprinkling ghc version tests throughout the code. They now all live in the GhcImplInfo record (from Distribution.Simple.GHC.ImplInfo) or for (g)hc-pkg they live in the HcPkgInfo record from Distribution.Simple.Program.HcPkg.

So initially I was going to say that this is a hc-pkg feature, and so it should be defined as a new field in HcPkgInfo, e.g. supportsLibDynDirs. However, I've changed my mind because it will be quite awkward since we cannot trivially get the HcPkgInfo value for the compiler, since not all of them support a hc-pkg.

@23Skidoo what do you reckon? In principle, perhaps this belongs in the Compiler value (from D.Simple.Compiler) since this question is valid whether or not the compiler uses a hc-pkg program. Indeed perhaps the Compiler type should contain a Maybe HcPkgInfo.

@christiaanb so if @23Skidoo agrees with me then I think you'd add this as a Bool feature of the Compiler type from Distribution.Simple.Compiler, and set it appropriately in the per-compiler configure functions.

Alternatively, could follow the approach of your TODO above and add per-compiler InstalledPackageInfo -> InstalledPackageInfo munging functions. Indeed we might be able to move the ABI stuff into those.

Copy link
Member

@23Skidoo 23Skidoo Oct 19, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd make libDynDirsSupported a function of type Compiler -> Bool instead of a field, which seems to be more in line with existing precedent (see profilingSupported and coverageSupported in D.S.Compiler). The alternative is probably also fine.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I created a function D.S.Compiler.supportsLibraryDynDir in the latest version of the PR.

@@ -390,11 +391,15 @@ filterConfigureFlags flags cabalLibVersion
configAllowNewer = Just (Cabal.AllowNewer Cabal.RelaxDepsNone)
}

-- Cabal < 1.25.0 doesn't know about --dynlibdir.
flags_1_25_0 = flags_latest { configInstallDirs = configInstallDirs_1_25_0}
configInstallDirs_1_25_0 = (configInstallDirs flags) { dynlibdir = NoFlag }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@23Skidoo I'm never too confident about the logic here. Can you double check.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

filterConfigureFlags changes are solid IMO.

@@ -423,7 +428,7 @@ filterConfigureFlags flags cabalLibVersion
-- Cabal < 1.18.0 doesn't know about --extra-prog-path and --sysconfdir.
flags_1_18_0 = flags_1_19_1 { configProgramPathExtra = toNubList []
, configInstallDirs = configInstallDirs_1_18_0}
configInstallDirs_1_18_0 = (configInstallDirs flags) { sysconfdir = NoFlag }
configInstallDirs_1_18_0 = (configInstallDirs flags_1_19_1) { sysconfdir = NoFlag }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this an independent bug fix?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It wasn't a "bug" until I added another configInstallDirs restriction. I mean, flags is the completely unrestricted flags, we should be using the restricted version: flags_1_19_1.

then dynlibdir installDirs :
extraLibDirs bi
else extraLibDirs bi
else [],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it might be easier to pull these out to the where clause (like the absinc, relink) and share the logic, e.g.

(libdir, dynlibdir)
  | not hasLibrary
  = (extraLibDirs bi, [])
    -- the dynamic-library-dirs defaults to the library-dirs if not specified,
    -- so this works if the dynamic-library-dirs field is supported or not

  | supportsLibraryDynDir comp
  = (libdir    installDirs : extraLibDirs bi,
     dynlibdir installDirs : extraLibDirs bi)

  | otherwise
  = (libdir installDirs : dynlibdir installDirs : extraLibDirs bi, [])
    -- the compiler doesn't understand the dynamic-library-dirs field so we
    -- add the dyn directory to the "normal" list in the library-dirs field

but do double check I've transcribed the logic correctly! :-)

-- more compilers start to support this, we should drop the
-- `supportsLibraryDynDir` check here, and just handle `IPI.libraryDynDirs`
-- in the actual package registration function belonging to those particular
-- compilers.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately we cannot do this yet given the structure of the code. We need to be able to generate the InstalledPackageInfo so we can write it to a file or script, without ending up calling the compiler specific registerPackage. What would be nice is if we had a compiler specific bit of generating the registration info, then we could do this compat bit there.

FYI, doing that might be an alternative to the thing I suggest below about compiler version tests.

@23Skidoo
Copy link
Member

AppVeyor failure seems to be real.

@ezyang
Copy link
Contributor

ezyang commented Oct 19, 2016

It looks like this regressed tests on GHC HEAD https://travis-ci.org/haskell/cabal/jobs/168959154

@christiaanb
Copy link
Collaborator Author

@ezyang Yes... this patch expects https://phabricator.haskell.org/D2611 to be merged into HEAD. What is the proper way to handle this?

@23Skidoo
Copy link
Member

23Skidoo commented Oct 20, 2016

@christiaanb I think we can use the same approach as in a088119 - change the version check from > 8.0.1 to > 8.0.1.201610XX.

@@ -321,6 +322,13 @@ unitIdSupported = ghcSupported "Uses unit IDs"
backpackSupported :: Compiler -> Bool
backpackSupported = ghcSupported "Support Backpack"

-- | Does this compiler support a package database entry with:
-- "dynamic-library-dirs"?
supportsLibraryDynDir :: Compiler -> Bool
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bikeshedding: libraryDynDirSupported would be more in line with existing precedent (see above).

@23Skidoo
Copy link
Member

Though I don't get why it's failing with 8.0.1 if the dynlibdir code path is > 8.0.1 only.

@christiaanb
Copy link
Collaborator Author

It fails on the 8.0.1 because that travis build has TEST_OTHER_VERSION=YES, so it also tests the testsuite using ghc-head. Anyhow, D2611 is not even merged in HEAD yet... so I don't know which exact GHC version it will be. I guess we'll have to wait until D2611 is merged.

`--dynlibdir` indicates the directory in which dynamic libraries
are installed. By default this setting is equal to:

`$libdir/$abi`

The static libraries will still end up in:

`$libdir/$libsubdir`

With `$libsubdir/$abi` as the default directory for dynamic
libraries, dynamic libraries will by default end up in a
single shared directory (per package database). This has the
potential to reduce start-up times for dynamically linked
executable as only one RPATH per package database will be
needed.

This commit uses the functionality defined in

https://phabricator.haskell.org/D2611

to tell GHC's > 8.0.1 package database that dynamic libraries
are copied to the directories mentioned in the

`dynamic-library-dirs`

field.
@christiaanb
Copy link
Collaborator Author

Ok, just talked with @bgamari and @dcoutts, D2611 will be merged today, so I've updated this patch to expect the changes in D2611 to live in GHC 8.0.1.20161021 or later.

@23Skidoo 23Skidoo merged commit 8cac8be into haskell:master Oct 20, 2016
@23Skidoo
Copy link
Member

Merged, thanks!

@23Skidoo
Copy link
Member

OK, why is CI still broken if the version bound is now correct?

@ezyang
Copy link
Contributor

ezyang commented Oct 21, 2016

It's because it was testing >= 8.0.1.20161021, but 8.1 nightlies are always greater than that, even without the fix. I pushed a fix.

@23Skidoo
Copy link
Member

Gah, I could've guessed.

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.

7 participants