Anonymous avatar Anonymous committed 8238336

Swap to using the ghc_alt as the tool since the 'pupeno' tool doesn't work.

Comments (0)

Files changed (3)

 
 #  A SCons tool to enable compilation of Haskell in SCons.
 #
-# Copyright © 2005 José Pablo Ezequiel "Pupeno" Fernández Silva
-# Copyright © 2009 Russel Winder
+#  Copyright © 2009 Russel Winder
 #
-#  This program is free software: you can redistribute it and/or modify it under the terms of the GNU
-#  General Public License as published by the Free Software Foundation, either version 3 of the License, or
-#  (at your option) any later version.
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
 #
-#  This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
-#  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
-#  License for more details.
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
 #
-#  You should have received a copy of the GNU General Public License along with this program.  If not, see
-#  <http://www.gnu.org/licenses/>.
-#
-#  Original this code was licenced under GPLv2.  This fork is relicenced under GPLv3 as is permitted.
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
-import SCons.Tool
-import SCons.Action
+#  This module is derived from the code to be found at http://www.scons.org/wiki/GhcBuilder.  That code has
+#  no attribution and no licence statement.
+
+from os.path import abspath, join
+from SCons.Builder import Builder
 from SCons.Scanner import Scanner
-from SCons.Defaults import ObjSourceScan, ArAction
-import os.path
-import string
+from SCons.Script  import *
+import re
+
+impdecl_regexp = re.compile(r"[\s]*import[\s]*(qualified)?[\s]*([\w\.]*).*")
+foreign_decl_regexp = re.compile(r"[\s]*foreign[\s]*(export|import)[\s]*ccall(.*\"[\s]*wrapper[\s]*\")?.*::.*")
+
+def find_foreign_declarations_that_require_stubs(node):
+        foreigns = foreign_decl_regexp.findall(node.get_contents())
+        for foreign in foreigns:
+                if foreign[0] == "export":
+                        return True
+                if foreign[1] != "":
+                        return True
+        return False
+
+def ghc_emitter(target, source, env):
+        src_name = str(source[0])
+        hi_name = src_name.replace(source[0].suffix, ".hi")
+        env.SideEffect(hi_name, target)
+        env.Clean(target, hi_name)
+        stubs = []
+        if find_foreign_declarations_that_require_stubs(source[0]):
+                stub_name = str(source[0]).replace(source[0].suffix, "_stub")
+                stubs.append(stub_name + ".o")
+                env.Clean(target, stub_name + ".c")
+                env.SideEffect(stub_name + ".h", target)
+                env.Clean(target, stub_name + ".h")
+        return (target + stubs, source)
+
+def ghc_path_function(env, dir, targets, sources):
+        if dir.path != ".":
+                env.AppendUnique(HSSEARCHPATH = [dir.path])
+        return tuple([dir.path] + env["HSSEARCHPATH"])
+
+def ghc_scanner_function(node, env, path):
+        from os.path import dirname, exists
+        imports = impdecl_regexp.findall(node.get_contents())
+        modules = map(lambda (qualified, module) : module, imports)
+
+        interfaces = []
+        for module in modules:
+                module = module.replace(".", "/")
+                interface = module + ".hi"
+                hs_file   = module + ".hs"
+                lhs_file  = module + ".lhs"
+                for dir in path:
+                        if exists(join(dir, hs_file)) or exists(join(dir, lhs_file)):
+                                interfaces.append(interface)
+                                break
+        return interfaces
+
+def exists(env):
+        return WhereIs("ghc")
 
 def generate(env):
-    env["HS"] = env.Detect("ghc") or "ghc"
-    env["HSLINK"] = "$HS $_LIBS $SOURCES -o $TARGET"
-    env["HSCOM"] = "$HS $_IMPORTS $_LIBS -c $SOURCE -o $TARGET"
-    env["_IMPORTS"] = "${_concat(IMPORTSPREFIX, LIBPATH, IMPORTSSUFFIX, __env__)}"
-    env["IMPORTSPREFIX"] = "-i"
-    env["IMPORTSSUFFIX"] = ""
-    env["_LIBS"] = "${_concat(LIBSPREFIX, LIBS, LIBSSUFFIX, __env__)}"
-    env["LIBSPREFIX"] = "-package "
-    env["LIBSSUFFIX"] = ""
-        
-    haskellSuffixes = [".hs", ".lhs"]
-        
-    compileAction = SCons.Action.Action("$HSCOM")
+        def _ghc_searchpath_opts(paths):
+                if paths:
+                        return reduce(lambda list, path: " -i" + path, paths, "")
+                else:
+                        return ""
+        env["_ghc_searchpath_opts"] = _ghc_searchpath_opts
+        def _ghc_package_opts(packages):
+                return reduce(lambda list, package: list + " -package " + package, packages, "")
+        env["_ghc_package_opts"] = _ghc_package_opts
 
-    linkAction = SCons.Action.Action("$HSLINK")
+        env["HSC"] = "ghc"
+        env["HSCFLAGS"] = []
+        env["HSLINKFLAGS"] = []
+        env["HSSEARCHPATH"] = []
+        env["HSPACKAGES"] = []
+        env["_HSPACKAGE_OPTS"] = "${_ghc_package_opts(HSPACKAGES)}"
+        env["_HSSEARCHPATH_OPTS"] = "${_ghc_searchpath_opts(HSSEARCHPATH)}"
 
-    def addHaskellInterface(target, source, env):
-        """ Add the .hi target with the same name as the object file. """
-        targetName = os.path.splitext(str(target[0]))[0]
-        return (target + [ targetName + ".hi"], source)
+        ghc_scanner = Scanner(
+                function = ghc_scanner_function,
+                skeys = [".hs", ".lhs"],
+                path_function = ghc_path_function
+                )
 
-    def importedModules(node, env, path):
-        """ Use ghc to find all the imported modules. """
+        ghc_c_compiler = Builder(
+                action = "$HSC $HSCFLAGS -c -o $TARGET $SOURCE",
+                src_suffix = [ ".c" ],
+                suffix = ".o",
+                single_source = True
+                )
 
-        #print "Figuring out dependencies for " + str(node)
-        def removeFile(fileName, errmsg = None):
-            """ Try to remove fileName, returns true on success, false otherwise. """
-            if os.path.exists(fileName):
-                try:
-                    os.remove(fileName)
-                except OSError:
-                    print "Unable to remove '%s'." % fileName
-                    return False
-            return True
+        ghc_compiler = Builder(
+                action = "$HSC $HSCFLAGS $_HSSEARCHPATH_OPTS -c -o $TARGET $SOURCE",
+                src_suffix = [ ".hs", ".lhs" ],
+                suffix = ".o",
+                single_source = True,
+                emitter = ghc_emitter,
+                source_scanner = ghc_scanner
+                )
 
-        # Generate the name of the file that is going to contain the dependency mappings.
-        fileName = os.path.join(os.path.dirname(str(node)),
-                                "." + os.path.basename(str(node)) + ".dep")
+        ghc_linker = Builder(
+                action = "$HSC $HSLINKFLAGS $_HSPACKAGE_OPTS -o $TARGET $SOURCES",
+                src_suffix = ".o",
+                suffix = "$PROGSUFFIX",
+                src_builder = [ ghc_compiler, ghc_c_compiler ]
+                )
 
-        # Just in case the file already exist, to avoid the creation of a .bak file, delete it.
-        if not removeFile(fileName):
-            print "Dependencies will not be calculated."
-            return []
-
-        # Build the command to obtain the dependency mapping from ghc.
-        command = ["ghc", "-M", "-optdep-f", "-optdep" + fileName]
-        if env._dict.has_key("LIBPATH"):
-            command += ["-i" + string.join(env["LIBPATH"], ":")]
-        command += [str(node)]
-        command = string.join(command)
-
-        commandIn, commandOut = os.popen4(command, "r")
-        errorMessage = commandOut.read()
-        commandIn.close()
-        commandOut.read()
-        if(errorMessage != ""):
-             print "An error ocurred running `%s`:" % command
-             for line in string.split(errorMessage, "\n"):
-                print ">" + line
-             print "Dependencies will not be calculated."
-             removeFile(fileName)
-             return []
-
-        try:
-            file = open(fileName, "r")
-            fileContents = file.read()
-            file.close()
-        except:
-            print "Unable to open '%s'." % fileName
-            print "Dependencies will not be calculated."
-            removeFile(fileName)
-            return []
-
-        fileContents = string.split(fileContents, "\n")
-
-        deps = []
-        for line in fileContents:
-            #print "deps=%s." % str(deps)
-            if len(line) > 0 and line[0] != "#":
-                files = string.split(line, ":")
-                target = string.strip(files[0])
-                source = string.strip(files[1])
-                if source != str(node): # and os.path.splitext(source)[1] != ".hi":
-                    deps += [os.path.basename(source)]
-                #if os.path.splitext(target)[0] != os.path.splitext(str(node))[0]:
-                #    deps += [os.path.basename(target)]
-                #print "   %s depends on %s." % (target, source)
-
-        removeFile(fileName)
-        #print "%s depends on %s." % (str(node), str(deps))
-        return deps
-
-    haskellScanner = Scanner(function = importedModules,
-                             name = "HaskellScanner",
-                             skeys = haskellSuffixes,
-                             recursive = False)
-
-    haskellProgram = SCons.Builder.Builder(action = linkAction,
-                                           prefix = "$PROGPREFIX",
-                                           suffix = "$PROGSUFFIX",
-                                           src_suffix = "$OBJSUFFIX",
-                                           src_builder = "HaskellObject")
-    env["BUILDERS"]["HaskellProgram"] = haskellProgram
-
-    haskellLibrary = SCons.Builder.Builder(action = SCons.Defaults.ArAction,
-                                           prefix = "$LIBPREFIX",
-                                           suffix = "$LIBSUFFIX",
-                                           src_suffix = "$OBJSUFFIX",
-                                           src_builder = "HaskellObject")
-    env["BUILDERS"]["HaskellLibrary"] = haskellLibrary
-
-    haskellObject = SCons.Builder.Builder(action = compileAction,
-                                          emitter = addHaskellInterface,
-                                          prefix = "$OBJPREFIX",
-                                          suffix = "$OBJSUFFIX",
-                                          src_suffix = haskellSuffixes,
-                                          source_scanner = haskellScanner)
-    env["BUILDERS"]["HaskellObject"] = haskellObject
-
-def exists(env):
-    return env.Detect(["ghc"])
+        env.Append( BUILDERS = { "HaskellProgram" : ghc_linker, "HaskellObject" : ghc_compiler } )

ghc_alt.py

-# -*- mode:python; coding:utf-8; -*-
-
-#  A SCons tool to enable compilation of Haskell in SCons.
-#
-#  Copyright © 2009 Russel Winder
-#
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to
-# permit persons to whom the Software is furnished to do so, subject to
-# the following conditions:
-#
-# The above copyright notice and this permission notice shall be included
-# in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
-# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
-# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-#  This module is derived from the code to be found at http://www.scons.org/wiki/GhcBuilder.  That code has
-#  no attribution and no licence statement.
-
-from os.path import abspath, join
-from SCons.Builder import Builder
-from SCons.Scanner import Scanner
-from SCons.Script  import *
-import re
-
-impdecl_regexp = re.compile(r"[\s]*import[\s]*(qualified)?[\s]*([\w\.]*).*")
-foreign_decl_regexp = re.compile(r"[\s]*foreign[\s]*(export|import)[\s]*ccall(.*\"[\s]*wrapper[\s]*\")?.*::.*")
-
-def find_foreign_declarations_that_require_stubs(node):
-        foreigns = foreign_decl_regexp.findall(node.get_contents())
-        for foreign in foreigns:
-                if foreign[0] == "export":
-                        return True
-                if foreign[1] != "":
-                        return True
-        return False
-
-def ghc_emitter(target, source, env):
-        src_name = str(source[0])
-        hi_name = src_name.replace(source[0].suffix, ".hi")
-        env.SideEffect(hi_name, target)
-        env.Clean(target, hi_name)
-        stubs = []
-        if find_foreign_declarations_that_require_stubs(source[0]):
-                stub_name = str(source[0]).replace(source[0].suffix, "_stub")
-                stubs.append(stub_name + ".o")
-                env.Clean(target, stub_name + ".c")
-                env.SideEffect(stub_name + ".h", target)
-                env.Clean(target, stub_name + ".h")
-        return (target + stubs, source)
-
-def ghc_path_function(env, dir, targets, sources):
-        if dir.path != ".":
-                env.AppendUnique(HSSEARCHPATH = [dir.path])
-        return tuple([dir.path] + env["HSSEARCHPATH"])
-
-def ghc_scanner_function(node, env, path):
-        from os.path import dirname, exists
-        imports = impdecl_regexp.findall(node.get_contents())
-        modules = map(lambda (qualified, module) : module, imports)
-
-        interfaces = []
-        for module in modules:
-                module = module.replace(".", "/")
-                interface = module + ".hi"
-                hs_file   = module + ".hs"
-                lhs_file  = module + ".lhs"
-                for dir in path:
-                        if exists(join(dir, hs_file)) or exists(join(dir, lhs_file)):
-                                interfaces.append(interface)
-                                break
-        return interfaces
-
-def exists(env):
-        return WhereIs("ghc")
-
-def generate(env):
-        def _ghc_searchpath_opts(paths):
-                if paths:
-                        return reduce(lambda list, path: " -i" + path, paths, "")
-                else:
-                        return ""
-        env["_ghc_searchpath_opts"] = _ghc_searchpath_opts
-        def _ghc_package_opts(packages):
-                return reduce(lambda list, package: list + " -package " + package, packages, "")
-        env["_ghc_package_opts"] = _ghc_package_opts
-
-        env["HSC"] = "ghc"
-        env["HSCFLAGS"] = []
-        env["HSLINKFLAGS"] = []
-        env["HSSEARCHPATH"] = []
-        env["HSPACKAGES"] = []
-        env["_HSPACKAGE_OPTS"] = "${_ghc_package_opts(HSPACKAGES)}"
-        env["_HSSEARCHPATH_OPTS"] = "${_ghc_searchpath_opts(HSSEARCHPATH)}"
-
-        ghc_scanner = Scanner(
-                function = ghc_scanner_function,
-                skeys = [".hs", ".lhs"],
-                path_function = ghc_path_function
-                )
-
-        ghc_c_compiler = Builder(
-                action = "$HSC $HSCFLAGS -c -o $TARGET $SOURCE",
-                src_suffix = [ ".c" ],
-                suffix = ".o",
-                single_source = True
-                )
-
-        ghc_compiler = Builder(
-                action = "$HSC $HSCFLAGS $_HSSEARCHPATH_OPTS -c -o $TARGET $SOURCE",
-                src_suffix = [ ".hs", ".lhs" ],
-                suffix = ".o",
-                single_source = True,
-                emitter = ghc_emitter,
-                source_scanner = ghc_scanner
-                )
-
-        ghc_linker = Builder(
-                action = "$HSC $HSLINKFLAGS $_HSPACKAGE_OPTS -o $TARGET $SOURCES",
-                src_suffix = ".o",
-                suffix = "$PROGSUFFIX",
-                src_builder = [ ghc_compiler, ghc_c_compiler ]
-                )
-
-        env.Append( BUILDERS = { "HaskellProgram" : ghc_linker, "HaskellObject" : ghc_compiler } )

haskell_pupeno.py

+# -*- mode:python; coding:utf-8; -*-
+
+#  A SCons tool to enable compilation of Haskell in SCons.
+#
+# Copyright © 2005 José Pablo Ezequiel "Pupeno" Fernández Silva
+# Copyright © 2009 Russel Winder
+#
+#  This program is free software: you can redistribute it and/or modify it under the terms of the GNU
+#  General Public License as published by the Free Software Foundation, either version 3 of the License, or
+#  (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+#  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+#  License for more details.
+#
+#  You should have received a copy of the GNU General Public License along with this program.  If not, see
+#  <http://www.gnu.org/licenses/>.
+#
+#  Original this code was licenced under GPLv2.  This fork is relicenced under GPLv3 as is permitted.
+
+import SCons.Tool
+import SCons.Action
+from SCons.Scanner import Scanner
+from SCons.Defaults import ObjSourceScan, ArAction
+import os.path
+import string
+
+def generate(env):
+    env["HS"] = env.Detect("ghc") or "ghc"
+    env["HSLINK"] = "$HS $_LIBS $SOURCES -o $TARGET"
+    env["HSCOM"] = "$HS $_IMPORTS $_LIBS -c $SOURCE -o $TARGET"
+    env["_IMPORTS"] = "${_concat(IMPORTSPREFIX, LIBPATH, IMPORTSSUFFIX, __env__)}"
+    env["IMPORTSPREFIX"] = "-i"
+    env["IMPORTSSUFFIX"] = ""
+    env["_LIBS"] = "${_concat(LIBSPREFIX, LIBS, LIBSSUFFIX, __env__)}"
+    env["LIBSPREFIX"] = "-package "
+    env["LIBSSUFFIX"] = ""
+        
+    haskellSuffixes = [".hs", ".lhs"]
+        
+    compileAction = SCons.Action.Action("$HSCOM")
+
+    linkAction = SCons.Action.Action("$HSLINK")
+
+    def addHaskellInterface(target, source, env):
+        """ Add the .hi target with the same name as the object file. """
+        targetName = os.path.splitext(str(target[0]))[0]
+        return (target + [ targetName + ".hi"], source)
+
+    def importedModules(node, env, path):
+        """ Use ghc to find all the imported modules. """
+
+        #print "Figuring out dependencies for " + str(node)
+        def removeFile(fileName, errmsg = None):
+            """ Try to remove fileName, returns true on success, false otherwise. """
+            if os.path.exists(fileName):
+                try:
+                    os.remove(fileName)
+                except OSError:
+                    print "Unable to remove '%s'." % fileName
+                    return False
+            return True
+
+        # Generate the name of the file that is going to contain the dependency mappings.
+        fileName = os.path.join(os.path.dirname(str(node)),
+                                "." + os.path.basename(str(node)) + ".dep")
+
+        # Just in case the file already exist, to avoid the creation of a .bak file, delete it.
+        if not removeFile(fileName):
+            print "Dependencies will not be calculated."
+            return []
+
+        # Build the command to obtain the dependency mapping from ghc.
+        command = ["ghc", "-M", "-optdep-f", "-optdep" + fileName]
+        if env._dict.has_key("LIBPATH"):
+            command += ["-i" + string.join(env["LIBPATH"], ":")]
+        command += [str(node)]
+        command = string.join(command)
+
+        commandIn, commandOut = os.popen4(command, "r")
+        errorMessage = commandOut.read()
+        commandIn.close()
+        commandOut.read()
+        if(errorMessage != ""):
+             print "An error ocurred running `%s`:" % command
+             for line in string.split(errorMessage, "\n"):
+                print ">" + line
+             print "Dependencies will not be calculated."
+             removeFile(fileName)
+             return []
+
+        try:
+            file = open(fileName, "r")
+            fileContents = file.read()
+            file.close()
+        except:
+            print "Unable to open '%s'." % fileName
+            print "Dependencies will not be calculated."
+            removeFile(fileName)
+            return []
+
+        fileContents = string.split(fileContents, "\n")
+
+        deps = []
+        for line in fileContents:
+            #print "deps=%s." % str(deps)
+            if len(line) > 0 and line[0] != "#":
+                files = string.split(line, ":")
+                target = string.strip(files[0])
+                source = string.strip(files[1])
+                if source != str(node): # and os.path.splitext(source)[1] != ".hi":
+                    deps += [os.path.basename(source)]
+                #if os.path.splitext(target)[0] != os.path.splitext(str(node))[0]:
+                #    deps += [os.path.basename(target)]
+                #print "   %s depends on %s." % (target, source)
+
+        removeFile(fileName)
+        #print "%s depends on %s." % (str(node), str(deps))
+        return deps
+
+    haskellScanner = Scanner(function = importedModules,
+                             name = "HaskellScanner",
+                             skeys = haskellSuffixes,
+                             recursive = False)
+
+    haskellProgram = SCons.Builder.Builder(action = linkAction,
+                                           prefix = "$PROGPREFIX",
+                                           suffix = "$PROGSUFFIX",
+                                           src_suffix = "$OBJSUFFIX",
+                                           src_builder = "HaskellObject")
+    env["BUILDERS"]["HaskellProgram"] = haskellProgram
+
+    haskellLibrary = SCons.Builder.Builder(action = SCons.Defaults.ArAction,
+                                           prefix = "$LIBPREFIX",
+                                           suffix = "$LIBSUFFIX",
+                                           src_suffix = "$OBJSUFFIX",
+                                           src_builder = "HaskellObject")
+    env["BUILDERS"]["HaskellLibrary"] = haskellLibrary
+
+    haskellObject = SCons.Builder.Builder(action = compileAction,
+                                          emitter = addHaskellInterface,
+                                          prefix = "$OBJPREFIX",
+                                          suffix = "$OBJSUFFIX",
+                                          src_suffix = haskellSuffixes,
+                                          source_scanner = haskellScanner)
+    env["BUILDERS"]["HaskellObject"] = haskellObject
+
+def exists(env):
+    return env.Detect(["ghc"])
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.