diff --git a/Cabal/src/Distribution/Simple/GHC.hs b/Cabal/src/Distribution/Simple/GHC.hs index f01d096e48c..656a258ca02 100644 --- a/Cabal/src/Distribution/Simple/GHC.hs +++ b/Cabal/src/Distribution/Simple/GHC.hs @@ -808,213 +808,72 @@ buildOrReplLib mReplFlags verbosity numJobs pkg_descr lbi lib clbi = do else do vanilla; shared whenProfLib (runGhcProg profOpts) + let + buildExtraSources mkSrcOpts wantDyn = traverse_ $ buildExtraSource mkSrcOpts wantDyn + buildExtraSource mkSrcOpts wantDyn filename = do + let baseSrcOpts = + mkSrcOpts + verbosity + implInfo + lbi + libBi + clbi + relLibTargetDir + filename + vanillaSrcOpts + -- Dynamic GHC requires C sources to be built + -- with -fPIC for REPL to work. See #2207. + | isGhcDynamic && wantDyn = baseSrcOpts{ghcOptFPic = toFlag True} + | otherwise = baseSrcOpts + runGhcProgIfNeeded opts = do + needsRecomp <- checkNeedsRecompilation filename opts + when needsRecomp $ runGhcProg opts + profSrcOpts = + vanillaSrcOpts + `mappend` mempty + { ghcOptProfilingMode = toFlag True + , ghcOptObjSuffix = toFlag "p_o" + } + sharedSrcOpts = + vanillaSrcOpts + `mappend` mempty + { ghcOptFPic = toFlag True + , ghcOptDynLinkMode = toFlag GhcDynamicOnly + , ghcOptObjSuffix = toFlag "dyn_o" + } + odir = fromFlag (ghcOptObjDir vanillaSrcOpts) + + createDirectoryIfMissingVerbose verbosity True odir + runGhcProgIfNeeded vanillaSrcOpts + unless (forRepl || not wantDyn) $ + whenSharedLib forceSharedLib (runGhcProgIfNeeded sharedSrcOpts) + unless forRepl $ + whenProfLib (runGhcProgIfNeeded profSrcOpts) + -- Build any C++ sources separately. unless (not has_code || null (cxxSources libBi)) $ do info verbosity "Building C++ Sources..." - sequence_ - [ do - let baseCxxOpts = - Internal.componentCxxGhcOptions - verbosity - implInfo - lbi - libBi - clbi - relLibTargetDir - filename - vanillaCxxOpts = - if isGhcDynamic - then baseCxxOpts{ghcOptFPic = toFlag True} - else baseCxxOpts - profCxxOpts = - vanillaCxxOpts - `mappend` mempty - { ghcOptProfilingMode = toFlag True - , ghcOptObjSuffix = toFlag "p_o" - } - sharedCxxOpts = - vanillaCxxOpts - `mappend` mempty - { ghcOptFPic = toFlag True - , ghcOptDynLinkMode = toFlag GhcDynamicOnly - , ghcOptObjSuffix = toFlag "dyn_o" - } - odir = fromFlag (ghcOptObjDir vanillaCxxOpts) - createDirectoryIfMissingVerbose verbosity True odir - let runGhcProgIfNeeded cxxOpts = do - needsRecomp <- checkNeedsRecompilation filename cxxOpts - when needsRecomp $ runGhcProg cxxOpts - runGhcProgIfNeeded vanillaCxxOpts - unless forRepl $ - whenSharedLib forceSharedLib (runGhcProgIfNeeded sharedCxxOpts) - unless forRepl $ whenProfLib (runGhcProgIfNeeded profCxxOpts) - | filename <- cxxSources libBi - ] + buildExtraSources Internal.componentCxxGhcOptions True (cxxSources libBi) -- build any C sources unless (not has_code || null (cSources libBi)) $ do info verbosity "Building C Sources..." - sequence_ - [ do - let baseCcOpts = - Internal.componentCcGhcOptions - verbosity - implInfo - lbi - libBi - clbi - relLibTargetDir - filename - vanillaCcOpts = - if isGhcDynamic - then -- Dynamic GHC requires C sources to be built - -- with -fPIC for REPL to work. See #2207. - baseCcOpts{ghcOptFPic = toFlag True} - else baseCcOpts - profCcOpts = - vanillaCcOpts - `mappend` mempty - { ghcOptProfilingMode = toFlag True - , ghcOptObjSuffix = toFlag "p_o" - } - sharedCcOpts = - vanillaCcOpts - `mappend` mempty - { ghcOptFPic = toFlag True - , ghcOptDynLinkMode = toFlag GhcDynamicOnly - , ghcOptObjSuffix = toFlag "dyn_o" - } - odir = fromFlag (ghcOptObjDir vanillaCcOpts) - createDirectoryIfMissingVerbose verbosity True odir - let runGhcProgIfNeeded ccOpts = do - needsRecomp <- checkNeedsRecompilation filename ccOpts - when needsRecomp $ runGhcProg ccOpts - runGhcProgIfNeeded vanillaCcOpts - unless forRepl $ - whenSharedLib forceSharedLib (runGhcProgIfNeeded sharedCcOpts) - unless forRepl $ whenProfLib (runGhcProgIfNeeded profCcOpts) - | filename <- cSources libBi - ] + buildExtraSources Internal.componentCcGhcOptions True (cSources libBi) -- build any JS sources unless (not has_code || not hasJsSupport || null (jsSources libBi)) $ do info verbosity "Building JS Sources..." - sequence_ - [ do - let vanillaJsOpts = - Internal.componentJsGhcOptions - verbosity - implInfo - lbi - libBi - clbi - relLibTargetDir - filename - profJsOpts = - vanillaJsOpts - `mappend` mempty - { ghcOptProfilingMode = toFlag True - , ghcOptObjSuffix = toFlag "p_o" - } - odir = fromFlag (ghcOptObjDir vanillaJsOpts) - createDirectoryIfMissingVerbose verbosity True odir - let runGhcProgIfNeeded jsOpts = do - needsRecomp <- checkNeedsRecompilation filename jsOpts - when needsRecomp $ runGhcProg jsOpts - runGhcProgIfNeeded vanillaJsOpts - unless forRepl $ whenProfLib (runGhcProgIfNeeded profJsOpts) - | filename <- jsSources libBi - ] + buildExtraSources Internal.componentJsGhcOptions False (jsSources libBi) -- build any ASM sources unless (not has_code || null (asmSources libBi)) $ do info verbosity "Building Assembler Sources..." - sequence_ - [ do - let baseAsmOpts = - Internal.componentAsmGhcOptions - verbosity - implInfo - lbi - libBi - clbi - relLibTargetDir - filename - vanillaAsmOpts = - if isGhcDynamic - then -- Dynamic GHC requires objects to be built - -- with -fPIC for REPL to work. See #2207. - baseAsmOpts{ghcOptFPic = toFlag True} - else baseAsmOpts - profAsmOpts = - vanillaAsmOpts - `mappend` mempty - { ghcOptProfilingMode = toFlag True - , ghcOptObjSuffix = toFlag "p_o" - } - sharedAsmOpts = - vanillaAsmOpts - `mappend` mempty - { ghcOptFPic = toFlag True - , ghcOptDynLinkMode = toFlag GhcDynamicOnly - , ghcOptObjSuffix = toFlag "dyn_o" - } - odir = fromFlag (ghcOptObjDir vanillaAsmOpts) - createDirectoryIfMissingVerbose verbosity True odir - let runGhcProgIfNeeded asmOpts = do - needsRecomp <- checkNeedsRecompilation filename asmOpts - when needsRecomp $ runGhcProg asmOpts - runGhcProgIfNeeded vanillaAsmOpts - unless forRepl $ - whenSharedLib forceSharedLib (runGhcProgIfNeeded sharedAsmOpts) - unless forRepl $ whenProfLib (runGhcProgIfNeeded profAsmOpts) - | filename <- asmSources libBi - ] + buildExtraSources Internal.componentAsmGhcOptions True (asmSources libBi) -- build any Cmm sources unless (not has_code || null (cmmSources libBi)) $ do info verbosity "Building C-- Sources..." - sequence_ - [ do - let baseCmmOpts = - Internal.componentCmmGhcOptions - verbosity - implInfo - lbi - libBi - clbi - relLibTargetDir - filename - vanillaCmmOpts = - if isGhcDynamic - then -- Dynamic GHC requires C sources to be built - -- with -fPIC for REPL to work. See #2207. - baseCmmOpts{ghcOptFPic = toFlag True} - else baseCmmOpts - profCmmOpts = - vanillaCmmOpts - `mappend` mempty - { ghcOptProfilingMode = toFlag True - , ghcOptObjSuffix = toFlag "p_o" - } - sharedCmmOpts = - vanillaCmmOpts - `mappend` mempty - { ghcOptFPic = toFlag True - , ghcOptDynLinkMode = toFlag GhcDynamicOnly - , ghcOptObjSuffix = toFlag "dyn_o" - } - odir = fromFlag (ghcOptObjDir vanillaCmmOpts) - createDirectoryIfMissingVerbose verbosity True odir - let runGhcProgIfNeeded cmmOpts = do - needsRecomp <- checkNeedsRecompilation filename cmmOpts - when needsRecomp $ runGhcProg cmmOpts - runGhcProgIfNeeded vanillaCmmOpts - unless forRepl $ - whenSharedLib forceSharedLib (runGhcProgIfNeeded sharedCmmOpts) - unless forRepl $ whenProfLib (runGhcProgIfNeeded profCmmOpts) - | filename <- cmmSources libBi - ] + buildExtraSources Internal.componentCmmGhcOptions True (cmmSources libBi) -- TODO: problem here is we need the .c files built first, so we can load them -- with ghci, but .c files can depend on .h files generated by ghc by ffi @@ -1550,6 +1409,9 @@ decodeMainIsArg arg data BuildSources = BuildSources { cSourcesFiles :: [FilePath] , cxxSourceFiles :: [FilePath] + , jsSourceFiles :: [FilePath] + , asmSourceFiles :: [FilePath] + , cmmSourceFiles :: [FilePath] , inputSourceFiles :: [FilePath] , inputSourceModules :: [ModuleName] } @@ -1600,6 +1462,9 @@ gbuildSources verbosity pkgId specVer tmpDir bm = BuildSources { cSourcesFiles = cSources bnfo , cxxSourceFiles = cxxSources bnfo + , jsSourceFiles = jsSources bnfo + , asmSourceFiles = asmSources bnfo + , cmmSourceFiles = cmmSources bnfo , inputSourceFiles = [main] , inputSourceModules = filter (/= mainModName) $ @@ -1610,6 +1475,9 @@ gbuildSources verbosity pkgId specVer tmpDir bm = BuildSources { cSourcesFiles = cSources bnfo , cxxSourceFiles = cxxSources bnfo + , jsSourceFiles = jsSources bnfo + , asmSourceFiles = asmSources bnfo + , cmmSourceFiles = cmmSources bnfo , inputSourceFiles = [main] , inputSourceModules = exeModules exe } @@ -1624,6 +1492,9 @@ gbuildSources verbosity pkgId specVer tmpDir bm = BuildSources { cSourcesFiles = csf , cxxSourceFiles = cxxsf + , jsSourceFiles = jsSources bnfo + , asmSourceFiles = asmSources bnfo + , cmmSourceFiles = cmmSources bnfo , inputSourceFiles = [] , inputSourceModules = exeModules exe } @@ -1633,6 +1504,9 @@ gbuildSources verbosity pkgId specVer tmpDir bm = BuildSources { cSourcesFiles = cSources bnfo , cxxSourceFiles = cxxSources bnfo + , jsSourceFiles = jsSources bnfo + , asmSourceFiles = asmSources bnfo + , cmmSourceFiles = cmmSources bnfo , inputSourceFiles = [] , inputSourceModules = foreignLibModules flib } @@ -1700,14 +1574,22 @@ gbuild verbosity numJobs pkg_descr lbi bm clbi = do let cSrcs = cSourcesFiles buildSources cxxSrcs = cxxSourceFiles buildSources + jsSrcs = jsSourceFiles buildSources + asmSrcs = asmSourceFiles buildSources + cmmSrcs = cmmSourceFiles buildSources inputFiles = inputSourceFiles buildSources inputModules = inputSourceModules buildSources isGhcDynamic = isDynamic comp dynamicTooSupported = supportsDynamicToo comp cLikeObjs = map (`replaceExtension` objExtension) cSrcs cxxObjs = map (`replaceExtension` objExtension) cxxSrcs + jsObjs = if hasJsSupport then map (`replaceExtension` objExtension) jsSrcs else [] + asmObjs = map (`replaceExtension` objExtension) asmSrcs + cmmObjs = map (`replaceExtension` objExtension) cmmSrcs needDynamic = gbuildNeedDynamic lbi bm needProfiling = withProfExe lbi + Platform hostArch _ = hostPlatform lbi + hasJsSupport = hostArch == JavaScript -- build executables baseOpts = @@ -1794,14 +1676,14 @@ gbuild verbosity numJobs pkg_descr lbi bm clbi = do PD.extraFrameworkDirs bnfo , ghcOptInputFiles = toNubListR - [tmpDir x | x <- cLikeObjs ++ cxxObjs] + [tmpDir x | x <- cLikeObjs ++ cxxObjs ++ jsObjs ++ cmmObjs ++ asmObjs] } dynLinkerOpts = mempty { ghcOptRPaths = rpaths , ghcOptInputFiles = toNubListR - [tmpDir x | x <- cLikeObjs ++ cxxObjs] + [tmpDir x | x <- cLikeObjs ++ cxxObjs ++ cmmObjs ++ asmObjs] } replOpts = baseOpts @@ -1876,95 +1758,74 @@ gbuild verbosity numJobs pkg_descr lbi bm clbi = do , ghcOptNumJobs = numJobs } + let + buildExtraSources mkSrcOpts wantDyn = traverse_ $ buildExtraSource mkSrcOpts wantDyn + buildExtraSource mkSrcOpts wantDyn filename = do + let baseSrcOpts = + mkSrcOpts + verbosity + implInfo + lbi + bnfo + clbi + tmpDir + filename + vanillaSrcOpts = + if isGhcDynamic && wantDyn + then -- Dynamic GHC requires C/C++ sources to be built + -- with -fPIC for REPL to work. See #2207. + baseSrcOpts{ghcOptFPic = toFlag True} + else baseSrcOpts + profSrcOpts = + vanillaSrcOpts + `mappend` mempty + { ghcOptProfilingMode = toFlag True + } + sharedSrcOpts = + vanillaSrcOpts + `mappend` mempty + { ghcOptFPic = toFlag True + , ghcOptDynLinkMode = toFlag GhcDynamicOnly + } + opts + | needProfiling = profSrcOpts + | needDynamic && wantDyn = sharedSrcOpts + | otherwise = vanillaSrcOpts + -- TODO: Placing all Haskell, C, & C++ objects in a single directory + -- Has the potential for file collisions. In general we would + -- consider this a user error. However, we should strive to + -- add a warning if this occurs. + odir = fromFlag (ghcOptObjDir opts) + + createDirectoryIfMissingVerbose verbosity True odir + needsRecomp <- checkNeedsRecompilation filename opts + when needsRecomp $ + runGhcProg opts + -- build any C++ sources unless (null cxxSrcs) $ do info verbosity "Building C++ Sources..." - sequence_ - [ do - let baseCxxOpts = - Internal.componentCxxGhcOptions - verbosity - implInfo - lbi - bnfo - clbi - tmpDir - filename - vanillaCxxOpts = - if isGhcDynamic - then -- Dynamic GHC requires C++ sources to be built - -- with -fPIC for REPL to work. See #2207. - baseCxxOpts{ghcOptFPic = toFlag True} - else baseCxxOpts - profCxxOpts = - vanillaCxxOpts - `mappend` mempty - { ghcOptProfilingMode = toFlag True - } - sharedCxxOpts = - vanillaCxxOpts - `mappend` mempty - { ghcOptFPic = toFlag True - , ghcOptDynLinkMode = toFlag GhcDynamicOnly - } - opts - | needProfiling = profCxxOpts - | needDynamic = sharedCxxOpts - | otherwise = vanillaCxxOpts - -- TODO: Placing all Haskell, C, & C++ objects in a single directory - -- Has the potential for file collisions. In general we would - -- consider this a user error. However, we should strive to - -- add a warning if this occurs. - odir = fromFlag (ghcOptObjDir opts) - createDirectoryIfMissingVerbose verbosity True odir - needsRecomp <- checkNeedsRecompilation filename opts - when needsRecomp $ - runGhcProg opts - | filename <- cxxSrcs - ] + buildExtraSources Internal.componentCxxGhcOptions True cxxSrcs -- build any C sources unless (null cSrcs) $ do info verbosity "Building C Sources..." - sequence_ - [ do - let baseCcOpts = - Internal.componentCcGhcOptions - verbosity - implInfo - lbi - bnfo - clbi - tmpDir - filename - vanillaCcOpts = - if isGhcDynamic - then -- Dynamic GHC requires C sources to be built - -- with -fPIC for REPL to work. See #2207. - baseCcOpts{ghcOptFPic = toFlag True} - else baseCcOpts - profCcOpts = - vanillaCcOpts - `mappend` mempty - { ghcOptProfilingMode = toFlag True - } - sharedCcOpts = - vanillaCcOpts - `mappend` mempty - { ghcOptFPic = toFlag True - , ghcOptDynLinkMode = toFlag GhcDynamicOnly - } - opts - | needProfiling = profCcOpts - | needDynamic = sharedCcOpts - | otherwise = vanillaCcOpts - odir = fromFlag (ghcOptObjDir opts) - createDirectoryIfMissingVerbose verbosity True odir - needsRecomp <- checkNeedsRecompilation filename opts - when needsRecomp $ - runGhcProg opts - | filename <- cSrcs - ] + buildExtraSources Internal.componentCcGhcOptions True cSrcs + + -- build any JS sources + unless (not hasJsSupport || null jsSrcs) $ do + info verbosity "Building JS Sources..." + buildExtraSources Internal.componentJsGhcOptions False jsSrcs + + -- build any ASM sources + unless (null asmSrcs) $ do + info verbosity "Building Assembler Sources..." + buildExtraSources Internal.componentAsmGhcOptions True asmSrcs + + -- build any Cmm sources + unless (null cmmSrcs) $ do + info verbosity "Building C-- Sources..." + buildExtraSources Internal.componentCmmGhcOptions True cmmSrcs -- TODO: problem here is we need the .c files built first, so we can load them -- with ghci, but .c files can depend on .h files generated by ghc by ffi diff --git a/cabal-testsuite/PackageTests/CmmSourcesExe/cabal.out b/cabal-testsuite/PackageTests/CmmSourcesExe/cabal.out new file mode 100644 index 00000000000..77b94906515 --- /dev/null +++ b/cabal-testsuite/PackageTests/CmmSourcesExe/cabal.out @@ -0,0 +1,8 @@ +# cabal v2-run +Resolving dependencies... +Build profile: -w ghc- -O1 +In order, the following will be built: + - cmmexperiment-0 (exe:demo) (first run) +Configuring executable 'demo' for cmmexperiment-0... +Preprocessing executable 'demo' for cmmexperiment-0... +Building executable 'demo' for cmmexperiment-0... diff --git a/cabal-testsuite/PackageTests/CmmSourcesExe/cabal.project b/cabal-testsuite/PackageTests/CmmSourcesExe/cabal.project new file mode 100644 index 00000000000..e6fdbadb439 --- /dev/null +++ b/cabal-testsuite/PackageTests/CmmSourcesExe/cabal.project @@ -0,0 +1 @@ +packages: . diff --git a/cabal-testsuite/PackageTests/CmmSourcesExe/cabal.test.hs b/cabal-testsuite/PackageTests/CmmSourcesExe/cabal.test.hs new file mode 100644 index 00000000000..0fa879eaedb --- /dev/null +++ b/cabal-testsuite/PackageTests/CmmSourcesExe/cabal.test.hs @@ -0,0 +1,6 @@ +import Test.Cabal.Prelude + +main = cabalTest $ do + res <- cabal' "v2-run" ["demo"] + assertOutputContains "= Post common block elimination =" res + assertOutputContains "In Box we have 0x" res diff --git a/cabal-testsuite/PackageTests/CmmSourcesExe/cbits/HeapPrim.cmm b/cabal-testsuite/PackageTests/CmmSourcesExe/cbits/HeapPrim.cmm new file mode 100644 index 00000000000..d4319291052 --- /dev/null +++ b/cabal-testsuite/PackageTests/CmmSourcesExe/cbits/HeapPrim.cmm @@ -0,0 +1,6 @@ +#include "Cmm.h" + +aToMyWordzh (P_ clos) +{ + return (clos); +} diff --git a/cabal-testsuite/PackageTests/CmmSourcesExe/cmmexperiment.cabal b/cabal-testsuite/PackageTests/CmmSourcesExe/cmmexperiment.cabal new file mode 100644 index 00000000000..b26391e6e84 --- /dev/null +++ b/cabal-testsuite/PackageTests/CmmSourcesExe/cmmexperiment.cabal @@ -0,0 +1,23 @@ +cabal-version: 3.0 +name: cmmexperiment +version: 0 +build-type: Simple + +-- This code is extracted form ghc-heap +-- Copyright (c) 2012-2013, Joachim Breitner +-- (and probably -2020 GHC Team) +-- Under BSD-3-Clause + +executable demo + default-language: Haskell2010 + main-is: Main.hs + hs-source-dirs: demo, src + build-depends: base + other-modules: Demo + cmm-sources: cbits/HeapPrim.cmm + if impl(ghc >=8.2) + cmm-options: -ddump-cmm-verbose + else + cmm-options: -ddump-cmm + + diff --git a/cabal-testsuite/PackageTests/CmmSourcesExe/demo/Main.hs b/cabal-testsuite/PackageTests/CmmSourcesExe/demo/Main.hs new file mode 100644 index 00000000000..e220ffc4c7c --- /dev/null +++ b/cabal-testsuite/PackageTests/CmmSourcesExe/demo/Main.hs @@ -0,0 +1,2 @@ +module Main (module Demo) where +import Demo (main) diff --git a/cabal-testsuite/PackageTests/CmmSourcesExe/setup.out b/cabal-testsuite/PackageTests/CmmSourcesExe/setup.out new file mode 100644 index 00000000000..c336268eaee --- /dev/null +++ b/cabal-testsuite/PackageTests/CmmSourcesExe/setup.out @@ -0,0 +1,5 @@ +# Setup configure +Configuring cmmexperiment-0... +# Setup build +Preprocessing executable 'demo' for cmmexperiment-0... +Building executable 'demo' for cmmexperiment-0... diff --git a/cabal-testsuite/PackageTests/CmmSourcesExe/setup.test.hs b/cabal-testsuite/PackageTests/CmmSourcesExe/setup.test.hs new file mode 100644 index 00000000000..7bf57f2628f --- /dev/null +++ b/cabal-testsuite/PackageTests/CmmSourcesExe/setup.test.hs @@ -0,0 +1,7 @@ +import Test.Cabal.Prelude + +main = setupTest $ do + skipUnlessGhcVersion ">= 7.8" + setup "configure" [] + res <- setup' "build" [] + assertOutputContains "= Post common block elimination =" res diff --git a/cabal-testsuite/PackageTests/CmmSourcesExe/src/Demo.hs b/cabal-testsuite/PackageTests/CmmSourcesExe/src/Demo.hs new file mode 100644 index 00000000000..ad44a3b650e --- /dev/null +++ b/cabal-testsuite/PackageTests/CmmSourcesExe/src/Demo.hs @@ -0,0 +1,37 @@ +{-# LANGUAGE CPP #-} +{-# LANGUAGE ForeignFunctionInterface #-} +{-# LANGUAGE GHCForeignImportPrim #-} +{-# LANGUAGE MagicHash #-} +{-# LANGUAGE UnliftedFFITypes #-} +module Demo (main) where + +#include "MachDeps.h" + +import Data.Bits +import GHC.Exts +import Numeric (showHex) + +foreign import prim "aToMyWordzh" aToWord# :: Any -> Word# + +tAG_MASK :: Int +tAG_MASK = (1 `shift` TAG_BITS) - 1 + +data Box = Box Any + +instance Show Box where + showsPrec _ (Box a) rs = + -- unsafePerformIO (print "↓" >> pClosure a) `seq` + pad_out (showHex addr "") ++ (if tag>0 then "/" ++ show tag else "") ++ rs + where + ptr = W# (aToWord# a) + tag = ptr .&. fromIntegral tAG_MASK -- ((1 `shiftL` TAG_BITS) -1) + addr = ptr - tag + pad_out ls = '0':'x':ls + +asBox :: a -> Box +asBox x = Box (unsafeCoerce# x) + +main :: IO () +main = do + let box = asBox "foobar" + putStrLn $ "In Box we have " ++ show box diff --git a/cabal-testsuite/PackageTests/JS/JsSourcesExe/cabal.project b/cabal-testsuite/PackageTests/JS/JsSourcesExe/cabal.project new file mode 100644 index 00000000000..e6fdbadb439 --- /dev/null +++ b/cabal-testsuite/PackageTests/JS/JsSourcesExe/cabal.project @@ -0,0 +1 @@ +packages: . diff --git a/cabal-testsuite/PackageTests/JS/JsSourcesExe/demo/Main.hs b/cabal-testsuite/PackageTests/JS/JsSourcesExe/demo/Main.hs new file mode 100644 index 00000000000..19e67f001f8 --- /dev/null +++ b/cabal-testsuite/PackageTests/JS/JsSourcesExe/demo/Main.hs @@ -0,0 +1,6 @@ +module Main where + +import Lib + +main :: IO () +main = foo diff --git a/cabal-testsuite/PackageTests/JS/JsSourcesExe/js-arch.test.hs b/cabal-testsuite/PackageTests/JS/JsSourcesExe/js-arch.test.hs new file mode 100644 index 00000000000..1fed749bdb8 --- /dev/null +++ b/cabal-testsuite/PackageTests/JS/JsSourcesExe/js-arch.test.hs @@ -0,0 +1,9 @@ +import Test.Cabal.Prelude + +main = setupAndCabalTest $ do + skipUnlessGhcVersion ">= 9.6" + skipUnlessJavaScript + skipIfWindows + + res <- cabal' "v2-run" ["demo"] + assertOutputContains "Hello JS!" res diff --git a/cabal-testsuite/PackageTests/JS/JsSourcesExe/jsbits/lib.js b/cabal-testsuite/PackageTests/JS/JsSourcesExe/jsbits/lib.js new file mode 100644 index 00000000000..125643b9a41 --- /dev/null +++ b/cabal-testsuite/PackageTests/JS/JsSourcesExe/jsbits/lib.js @@ -0,0 +1,3 @@ +function foo() { + console.log("Hello JS!"); +} diff --git a/cabal-testsuite/PackageTests/JS/JsSourcesExe/jssources-exe.cabal b/cabal-testsuite/PackageTests/JS/JsSourcesExe/jssources-exe.cabal new file mode 100644 index 00000000000..3e19513ac9b --- /dev/null +++ b/cabal-testsuite/PackageTests/JS/JsSourcesExe/jssources-exe.cabal @@ -0,0 +1,20 @@ +cabal-version: 3.0 +name: jssources-exe +version: 0 +build-type: Simple + +library + default-language: Haskell2010 + if arch(JavaScript) + hs-source-dirs: srcJS + else + hs-source-dirs: src + exposed-modules: Lib + build-depends: base + +executable demo + default-language: Haskell2010 + main-is: Main.hs + hs-source-dirs: demo + js-sources: jsbits/lib.js + build-depends: base, jssources-exe diff --git a/cabal-testsuite/PackageTests/JS/JsSourcesExe/other-arch.out b/cabal-testsuite/PackageTests/JS/JsSourcesExe/other-arch.out new file mode 100644 index 00000000000..96e1bbadcf9 --- /dev/null +++ b/cabal-testsuite/PackageTests/JS/JsSourcesExe/other-arch.out @@ -0,0 +1,12 @@ +# cabal v2-run +Resolving dependencies... +Build profile: -w ghc- -O1 +In order, the following will be built: + - jssources-exe-0 (lib) (first run) + - jssources-exe-0 (exe:demo) (first run) +Configuring library for jssources-exe-0... +Preprocessing library for jssources-exe-0... +Building library for jssources-exe-0... +Configuring executable 'demo' for jssources-exe-0... +Preprocessing executable 'demo' for jssources-exe-0... +Building executable 'demo' for jssources-exe-0... diff --git a/cabal-testsuite/PackageTests/JS/JsSourcesExe/other-arch.test.hs b/cabal-testsuite/PackageTests/JS/JsSourcesExe/other-arch.test.hs new file mode 100644 index 00000000000..187a9cf73bd --- /dev/null +++ b/cabal-testsuite/PackageTests/JS/JsSourcesExe/other-arch.test.hs @@ -0,0 +1,7 @@ +import Test.Cabal.Prelude + +main = cabalTest $ do + skipIfJavaScript + -- Ensure the field `js-sources` does not raise issues + res <- cabal' "v2-run" ["demo"] + assertOutputContains "Hello Not JS!" res diff --git a/cabal-testsuite/PackageTests/JS/JsSourcesExe/src/Lib.hs b/cabal-testsuite/PackageTests/JS/JsSourcesExe/src/Lib.hs new file mode 100644 index 00000000000..7937e6f34ed --- /dev/null +++ b/cabal-testsuite/PackageTests/JS/JsSourcesExe/src/Lib.hs @@ -0,0 +1,4 @@ +module Lib where + +foo :: IO () +foo = putStrLn "Hello Not JS!" diff --git a/cabal-testsuite/PackageTests/JS/JsSourcesExe/srcJS/Lib.hs b/cabal-testsuite/PackageTests/JS/JsSourcesExe/srcJS/Lib.hs new file mode 100644 index 00000000000..af628af03ec --- /dev/null +++ b/cabal-testsuite/PackageTests/JS/JsSourcesExe/srcJS/Lib.hs @@ -0,0 +1,3 @@ +module Lib where + +foreign import javascript foo :: IO () diff --git a/changelog.d/issue-8639 b/changelog.d/issue-8639 new file mode 100644 index 00000000000..18d8606c690 --- /dev/null +++ b/changelog.d/issue-8639 @@ -0,0 +1,12 @@ +synopsis: Add support for asm, cmm, and js sources in executable components +packages: Cabal +prs: #9061 +issues: #8639 +significance: significant + +description: { + +Executable components now support the inclusion of asm, cmm, and js source files in a cabal file using the same syntax as is used for these sources in library components, similar to how c and c++ sources are supported in both types of components. This syntax was already parsed in cabal files, but was silently ignored in the build step, so no changes to syntax are made. + +} +