-
Notifications
You must be signed in to change notification settings - Fork 677
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 support for building profiled dynamic way #9900
base: master
Are you sure you want to change the base?
Conversation
mpickering
commented
Apr 17, 2024
•
edited
edited
I require the version to be bumped to 3.13 before this can be finished. |
680c3a2
to
70b5f74
Compare
c1f27fe
to
cb44290
Compare
The test fails on 8.6.5 because of this GHC bug (fixed in 2018): e400b9babdcf11669f963aeec20078fe7ccfca0d |
fd810d4
to
d47096e
Compare
New options for cabal.project and ./Setup interface: * `profiling-shared`: Enable building profiling dynamic way * Passing `--enable-profiling` and `--enable-executable-dynamic` builds profiled dynamic executables. Support for using `profiling-shared` is guarded behind a constraint which ensures you are using `Cabal >= 3.13`. In the cabal file: * `ghc-prof-shared-options`, for passing options when building in profiling dynamic way Other miscellenious fixes and improvements * Some refactoring around ways so that which ways we should build for a library, foreign library and executable is computed by the `buildWays` function (rather than ad-hoc in three different places). * Improved logic for detecting whether a compiler supports compiling a specific way. See functions `profilingVanillaSupported`, `dynamicSupported`, `profilingDynamicSupported` etc These functions report accurate infomation after ghc-9.10.1. * Fixed logic for determining whether to build shared libraries. (see haskell#10050) Now, if you explicitly enable `--*-shared`, then that will always take effect. If it's not specified then `--enable-executable-dynamic` will turn on shared libraries IF `--enable-profiling` is not enabled. * Remove assumption that dynamically linked compilers can build dynamic libraries (they might be cross compilers. * Query the build compiler to determine which library way is necessary to be built for TH support to work. (rather than assume all compilers are dynamically linked) * An extensive test which checks how options for `./Setup` and `cabal-install` are translated into build ways. Fixes haskell#4816, haskell#10049, haskell#10050
@@ -807,6 +803,20 @@ computeLocalBuildConfig cfg comp programDb = do | |||
, relocatable = fromFlagOrDefault False $ configRelocatable cfg | |||
} | |||
|
|||
-- Dynamic executable, but no shared vanilla libararies |
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.
-- Dynamic executable, but no shared vanilla libararies | |
-- Dynamic executable, but no shared vanilla libraries |
++ "is not being built. Linking will fail if any executables " | ||
++ "depend on the library." | ||
|
||
-- Profiled dynamic executable, but no shared profiling libararies |
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.
-- Profiled dynamic executable, but no shared profiling libararies | |
-- Profiled dynamic executable, but no shared profiling libraries |
return $ \buildOptions -> apply buildOptions{LBC.withProfLibShared = tryLibProfilingShared} | ||
else -- Case 2: Compiler doesn't support profiling shared so turn them off | ||
do | ||
-- If we wanted to enable profilng shared libraries.. tell the |
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.
-- If we wanted to enable profilng shared libraries.. tell the | |
-- If we wanted to enable profiling shared libraries.. tell the |
, LBC.withProfLib = profilingVanillaSupportedOrUnknown comp && (tryLibProfilingShared || LBC.withProfLib original_options) | ||
, LBC.withDynExe = if LBC.withProfExe original_options then False else LBC.withDynExe original_options | ||
} | ||
return (tryExeProfiling && not (tryLibProfiling || tryLibProfilingShared), apply2) |
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.
Can you move the "when exeProfWithoutLibProf " warning into here, and then refactor to not return this boolean? I find it too complicated right now.
] | ||
whenGHCi $ installOrdinary builtDir targetDir ghciLibName | ||
ProfWay -> do | ||
installOrdinary builtDir targetDir profileLibName |
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.
Why doesn't this code path include any logic to deal with extraBundledLibs
that all other paths include? (I know you didn't change this.)
forM_ (neededLibWays isIndef) $ \case | ||
StaticWay -> compileIfNeeded vanillaSrcOpts | ||
DynWay -> compileIfNeeded sharedSrcOpts{ghcOptObjSuffix = toFlag "dyn_o"} | ||
ProfWay -> compileIfNeeded profSrcOpts{ghcOptObjSuffix = toFlag "p_o"} | ||
ProfDynWay -> compileIfNeeded profSharedSrcOpts{ghcOptObjSuffix = toFlag "p_dyn_o"} | ||
CFLib flib -> | ||
case neededFLibWay (withDynFLib flib) of | ||
StaticWay -> compileIfNeeded vanillaSrcOpts | ||
DynWay -> compileIfNeeded sharedSrcOpts | ||
ProfWay -> compileIfNeeded profSrcOpts | ||
ProfDynWay -> compileIfNeeded profSharedSrcOpts | ||
-- For the remaining component types (Exec, Test, Bench), we also | ||
-- determine with which options to build the objects (vanilla vs shared vs | ||
-- profiled), but predicate is the same for the three kinds. | ||
_exeLike -> | ||
case neededExeWay of | ||
StaticWay -> compileIfNeeded vanillaSrcOpts | ||
DynWay -> compileIfNeeded sharedSrcOpts | ||
ProfWay -> compileIfNeeded profSrcOpts | ||
ProfDynWay -> compileIfNeeded profSharedSrcOpts |
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.
Good improvement.👍
wantedFLibWay is_dyn_flib = | ||
case (is_dyn_flib, withProfExe lbi) of | ||
(True, True) -> ProfDynWay | ||
(False, True) -> ProfWay | ||
(True, False) -> DynWay | ||
(False, False) -> StaticWay | ||
|
||
wantedExeWay = | ||
case (withDynExe lbi, withProfExe lbi) of | ||
(True, True) -> ProfDynWay | ||
(True, False) -> DynWay | ||
(False, True) -> ProfWay | ||
(False, False) -> StaticWay |
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.
Good that you got rid of the sketchy if isLib then id else take 1
that was there before. 👍
(False, True) -> ProfWay | ||
(False, False) -> StaticWay | ||
in | ||
(wantedLibWays, wantedFLibWay, wantedExeWay) |
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.
What happened to the following logic:
neededWays =
wantedWays
<> Set.fromList
-- TODO: You also don't need to build the GHC way when doing TH if
-- you are using an external interpreter!!
[defaultGhcWay | doingTH && defaultGhcWay `Set.notMember` wantedWays]
?
|
||
-- TODO: [code cleanup] move this into the Cabal lib. It's currently open | ||
-- coded in Distribution.Simple.Configure, but should be made a proper | ||
-- function of the Compiler or CompilerInfo. | ||
compilerShouldUseSharedLibByDefault = | ||
case compilerFlavor compiler of | ||
GHC -> GHC.isDynamic compiler | ||
GHC -> GHC.compilerBuildWay compiler == DynWay && canBuildSharedLibs |
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.
Is it intended that this is false if compilerBuildWay == ProfDynWay
?
@@ -734,7 +735,7 @@ computeLocalBuildConfig cfg comp programDb = do | |||
CompilerId GHC _ -> | |||
-- if ghc is dynamic, then ghci needs a shared | |||
-- library, so we build one by default. | |||
GHC.isDynamic comp | |||
GHC.compilerBuildWay comp == DynWay |
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.
Is the logic consistent here? If we have --enable-executable-dynamic --enable-profiling
, do we want sharedLibsByDefault
to be True
?
Conversely, why don't we have GHC.compilerBuildWay comp `elem` [DynWay, ProfDynWay]
? What will happen with ProfDyn
and ghci? Is that supported?