gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] [taler-taler-build-scripts] branch master updated: build sc


From: gnunet
Subject: [GNUnet-SVN] [taler-taler-build-scripts] branch master updated: build scripts as library
Date: Mon, 14 Oct 2019 18:52:20 +0200

This is an automated email from the git hooks/post-receive script.

dold pushed a commit to branch master
in repository taler-build-scripts.

The following commit(s) were added to refs/heads/master by this push:
     new ab8503f  build scripts as library
ab8503f is described below

commit ab8503f11de99b030368d24faf7c8788de9eb84e
Author: Florian Dold <address@hidden>
AuthorDate: Mon Oct 14 22:03:24 2019 +0530

    build scripts as library
---
 .gitignore            |   1 +
 README                |  15 ++-
 bootstrap.template    |  14 +++
 configure.py          | 226 -----------------------------------------
 configure.py.template |  20 ++++
 talerbuildconfig.py   | 275 ++++++++++++++++++++++++++++++++++++++++++++++++++
 testconfigure.py      |  13 +++
 7 files changed, 337 insertions(+), 227 deletions(-)

diff --git a/.gitignore b/.gitignore
index aee2e4c..ed077ae 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
 config.mk
+__pycache__
diff --git a/README b/README
index fce232a..2b2e5a5 100644
--- a/README
+++ b/README
@@ -1 +1,14 @@
-shared build-system files for (some) parts of Taler.
+Shared build-system files for (some) parts of Taler.
+
+A repository using these build-system files should be structured as follows:
+
+<my-repository.git>
+- bootstrap (copied/adjusted from bootstrap.template)
+- build-system (directory containing build system "stuff")
+--| configure.py (copied/adjusted from bootstrap.template)
+--| taler-build-scripts (git submodule of taler-build-scripts)
+--| Makefile
+
+Makefile and configure.py can also be placed directly into the root of the
+repository.  However, this might lead to errors when "make" can be invoked
+before bootstrap and configure has been done.
diff --git a/bootstrap.template b/bootstrap.template
new file mode 100755
index 0000000..82700e1
--- /dev/null
+++ b/bootstrap.template
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+# Bootstrap the repository.  Used when the repository is checked out from git.
+# When using the source tarball, running this script is not necessary.
+
+set -eu
+
+if ! git --version >/dev/null; then
+  echo "git not installed"
+  exit 1
+fi
+
+git submodule update --init
+cp build-system/taler-build-scripts/configure ./configure
diff --git a/configure.py b/configure.py
deleted file mode 100644
index 4406560..0000000
--- a/configure.py
+++ /dev/null
@@ -1,226 +0,0 @@
-# This file is part of TALER
-# (C) 2019 GNUnet e.V.
-#
-# Authors:
-# Author: ng0 <address@hidden>
-#
-# Permission to use, copy, modify, and/or distribute this software for any
-# purpose with or without fee is hereby granted.
-#
-# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
-# LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
-# OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
-# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-# ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
-# THIS SOFTWARE.
-#
-# SPDX-License-Identifier: 0BSD
-
-import argparse
-import os
-import sys
-import logging
-from distutils.spawn import find_executable
-import subprocess
-
-"""
-This application aims to replicate a small GNU Coding Standards
-configure script, taylored at projects in GNU Taler. We hope it
-can be of use outside of GNU Taler, hence it is dedicated to the
-public domain ('0BSD').
-It takes a couple of arguments on the commandline equivalent to
-configure by autotools, in addition some environment variables
-xan take precedence over the switches. In the absence of switches,
-/usr/local is assumed as the PREFIX.
-When  all data from tests are gathered, it generates a config.mk
-Makefile fragement, which is the processed by a Makefile (usually) in
-GNU Make format.
-"""
-
-
-def existence(name):
-    return find_executable(name) is not None
-
-
-def tool_version(name):
-    return subprocess.getstatusoutput(name)[1]
-
-
-def tool_emscripten():
-    if existence('emcc'):
-        emscripten_version = tool_version('emcc --version')
-        return f"emscripten version {emscripten_version} found"
-    else:
-        return f"emscripten compiler not found"
-
-
-def tool_pybabel():
-    # No suffix. Would probably be cheaper to do this in
-    # the dict as well.
-    if existence('pybabel'):
-        return 'pybabel'
-    else:
-        # Has suffix, try suffix. We know the names in advance,
-        # so use a dictionary and iterate over it. Use enough names
-        # to safe updating this for another couple of years.
-        #
-        # Food for thought: If we only accept python 3.7 or higher,
-        # is checking pybabel + pybabel-3.[0-9]* too much and could
-        # be broken down to pybabel + pybabel-3.7 and later names?
-        version_dict = {
-            '3.0': 'pybabel-3.0',
-            '3.1': 'pybabel-3.1',
-            '3.2': 'pybabel-3.2',
-            '3.3': 'pybabel-3.3',
-            '3.4': 'pybabel-3.4',
-            '3.5': 'pybabel-3.5',
-            '3.6': 'pybabel-3.6',
-            '3.7': 'pybabel-3.7',
-            '3.8': 'pybabel-3.8',
-            '3.9': 'pybabel-3.9',
-            '4.0': 'pybabel-4.0',
-        }
-        for value in version_dict.values():
-            if existence(value):
-                return value
-
-
-def tool_browser():
-    # TODO: read xdg-open value first.
-    browser_dict = {
-        'ice': 'icecat',
-        'ff': 'firefox',
-        'chg': 'chrome',
-        'ch': 'chromium',
-        'o': 'opera'
-    }
-    if 'BROWSER' in os.environ:
-        return os.environ.get('BROWSER')
-    else:
-        for value in browser_dict.values():
-            if existence(value):
-                return value
-
-
-def tool_node():
-    if existence('node') is None:
-        sys.exit(
-            'Error: node executable not found.\nIf you are using Ubuntu Linux 
or Debian Linux, try installing the\nnode-legacy package or symlink node to 
nodejs.'
-        )
-    else:
-        if subprocess.getstatusoutput(
-            "node -p 'process.exit(!(/v([0-9]+)/.exec(process.version)[1] >= 
4))'"
-        )[1] is not '':
-            sys.exit('Your node version is too old, use Node 4.x or newer')
-        else:
-            node_version = tool_version("node --version")
-            return f"Using Node version {node_version}"
-
-
-def tool_yarn():
-    if existence('yarn'):
-        p1 = subprocess.run(['yarn', 'help'],
-                            stderr=subprocess.STDOUT,
-                            stdout=subprocess.PIPE)
-        if 'No such file or directory' in p1.stdout.decode('utf-8'):
-            if existence('cmdtest'):
-                print(
-                    'WARNING: cmdtest is installed, this can lead\nto know 
issues with yarn.'
-                )
-            sys.exit(
-                'ERROR: You seem to have the wrong kind of "yarn" installed, 
please remove the\nconflicting binary before continuing!'
-            )
-        return 'yarn'
-    elif existence('yarnpkg'):
-        return 'yarnpkg'
-    else:
-        sys.exit(
-            'ERROR: yarn missing. See https://yarnpkg.com/en/docs/install\n'
-        )
-
-
-def tool_posix():
-    messages = []
-
-    tool_find = existence('find')
-    if tool_find is None:
-        messages.append('prerequisite find(1) not found.')
-
-    tool_xargs = existence('xargs')
-    if tool_xargs is None:
-        messages.append('prerequisite xargs(1) not found.')
-
-    tool_msgmerge = existence('msgmerge')
-    if tool_msgmerge is None:
-        messages.append('prerequisite msgmerge(1) not found.')
-
-    return messages
-
-
-def main():
-    logging.basicConfig(level=logging.DEBUG)
-    logger = logging.getLogger(__name__)
-
-    parser = argparse.ArgumentParser()
-    parser.add_argument(
-        '-p',
-        '--prefix',
-        type=str,
-        default='/usr/local',
-        help='Directory prefix for installation'
-    )
-    parser.add_argument(
-        '-yarn', '--with-yarn', type=str, help='name of yarn executable'
-    )
-    parser.add_argument(
-        '-browser',
-        '--with-browser',
-        type=str,
-        help='name of your webbrowser executable'
-    )
-    parser.add_argument(
-        '-pybabel',
-        '--with-pybabel',
-        type=str,
-        help='name of your pybabel executable'
-    )
-    args = parser.parse_args()
-    if 'DEBUG' in os.environ:
-        logger.debug('%s', args)
-
-    # get PREFIX
-    if 'PREFIX' in os.environ:
-        p_myprefix = os.environ.get('PREFIX')
-        if p_myprefix is not None and os.path.isdir(p_myprefix) is True:
-            myprefix = p_myprefix
-    elif args.prefix is not '/usr/local':
-        myprefix = args.prefix
-    else:
-        myprefix = parser.get_default('prefix')
-
-    # get yarn executable
-    if args.with_yarn is not None:
-        yarnexe = args.with_yarn
-    else:
-        yarnexe = str(tool_yarn())
-
-    mybrowser = tool_browser()
-    mypybabel = tool_pybabel()
-    f = open('config.mk', 'w+')
-    f.writelines([
-        '# This mk fragment is autogenerated by configure.py\n',
-        f'prefix={myprefix}\n', f'yarnexe={yarnexe}\n',
-        f'RUN_BROWSER={mybrowser}\n', f'pybabel={mypybabel}\n'
-    ])
-    f.close()
-    print(tool_node())
-    print(tool_emscripten())
-    posixlist = tool_posix()
-    for msg in posixlist:
-        print(posixlist[msg])
-
-
-if __name__ == "__main__":
-    main()
diff --git a/configure.py.template b/configure.py.template
new file mode 100755
index 0000000..f55fec1
--- /dev/null
+++ b/configure.py.template
@@ -0,0 +1,20 @@
+#!/usr/bin/env python3
+
+import sys
+from pathlib import Path
+
+base_dir = Path(__file__, "../build-system/taler-build-scripts").resolve()
+if not base_dir.exists():
+    print(
+        f"build system directory ({base_dir}) missing", file=sys.stderr
+    )
+    sys.exit(1)
+sys.path.insert(0, base_dir)
+
+from talerbuildconfig import *
+
+b = BuildConfig()
+b.enable_prefix()
+b.enable_configmk()
+b.add_tool(PosixTool("find"))
+b.run()
diff --git a/talerbuildconfig.py b/talerbuildconfig.py
new file mode 100644
index 0000000..95f0fa2
--- /dev/null
+++ b/talerbuildconfig.py
@@ -0,0 +1,275 @@
+# This file is part of TALER
+# (C) 2019 GNUnet e.V.
+#
+# Authors:
+# Author: ng0 <address@hidden>
+# Author: Florian Dold <address@hidden>
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
+# LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
+# OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+# ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+# THIS SOFTWARE.
+#
+# SPDX-License-Identifier: 0BSD
+
+from abc import ABC
+import argparse
+import os
+import sys
+import logging
+from distutils.spawn import find_executable
+import subprocess
+from dataclasses import dataclass
+
+"""
+This module aims to replicate a small GNU Coding Standards
+configure script, taylored at projects in GNU Taler. We hope it
+can be of use outside of GNU Taler, hence it is dedicated to the
+public domain ('0BSD').
+It takes a couple of arguments on the commandline equivalent to
+configure by autotools, in addition some environment variables
+xan take precedence over the switches. In the absence of switches,
+/usr/local is assumed as the PREFIX.
+When  all data from tests are gathered, it generates a config.mk
+Makefile fragement, which is the processed by a Makefile (usually) in
+GNU Make format.
+"""
+
+
+class Tool(ABC):
+    def args(self):
+        ...
+
+    def check(self, buildconfig):
+        ...
+
+
+class BuildConfig:
+    def __init__(self):
+        # Pairs of (key, value) for config.mk variables
+        self.make_variables = []
+        self.tools = []
+        self.tool_results = {}
+        self.args = None
+        self.prefix_enabled = False
+        self.configmk_enabled = False
+
+    def add_tool(self, tool):
+        if isinstance(tool, Tool):
+            self.tools.append(tool)
+        else:
+            raise Exception("Not a tool instance: " + repr(tool))
+
+    def _set_tool(self, name, value, version=None):
+        self.tool_results[name] = (value, version)
+
+    def enable_prefix(self):
+        """If enabled, process the --prefix argument."""
+        self.prefix_enabled = True
+
+    def enable_configmk(self):
+        """If enabled, output the config.mk makefile fragment."""
+        self.configmk_enabled = True
+
+    def run(self):
+        parser = argparse.ArgumentParser()
+        if self.prefix_enabled:
+            parser.add_argument(
+                "--prefix",
+                type=str,
+                default="/usr/local",
+                help="Directory prefix for installation",
+            )
+        for tool in self.tools:
+            tool.args(parser)
+        args = self.args = parser.parse_args()
+
+        for tool in self.tools:
+            res = tool.check(self)
+            if not res:
+                print(f"Error: tool {tool.name} not available")
+                if hasattr(tool, "hint"):
+                    print(f"Hint: {tool.hint}")
+
+        for tool in self.tools:
+            path, version = self.tool_results[tool.name]
+            if version is None:
+                print(f"found {tool.name} as {path}")
+            else:
+                print(f"found {tool.name} as {path} (version {version})")
+
+        if self.configmk_enabled:
+            with open("config.mk", "w") as f:
+                f.write("# this makefile fragment is autogenerated by 
configure.py\n")
+                if self.prefix_enabled:
+                    f.write(f"prefix = {args.prefix}\n")
+                for tool in self.tools:
+                    path, version = self.tool_results[tool.name]
+                    f.write(f"{tool.name} = {path}\n")
+
+
+def existence(name):
+    return find_executable(name) is not None
+
+
+class YarnTool(Tool):
+    name = "yarn"
+    description = "The yarn package manager for node"
+
+    def args(self, parser):
+        parser.add_argument("--with-yarn", action="store")
+
+    def check(self, buildconfig):
+        yarn_arg = buildconfig.args.with_yarn
+        if yarn_arg is not None:
+            buildconfig._set_tool("yarn", yarn_arg)
+            return True
+        if existence("yarn"):
+            p1 = subprocess.run(
+                ["yarn", "help"], stderr=subprocess.STDOUT, 
stdout=subprocess.PIPE
+            )
+            if "No such file or directory" in p1.stdout.decode("utf-8"):
+                if existence("cmdtest"):
+                    buildconfig._warn(
+                        "cmdtest is installed, this can lead to known issues 
with yarn."
+                    )
+                buildconfig._error(
+                    "You seem to have the wrong kind of 'yarn' installed.\n"
+                    "Please remove the conflicting binary before proceeding"
+                )
+                return False
+            yarn_version = tool_version("yarn --version")
+            buildconfig._set_tool("yarn", "yarn", yarn_version)
+            return True
+        elif existence("yarnpkg"):
+            yarn_version = tool_version("yarnpkg --version")
+            buildconfig._set_tool("yarn", "yarnpkg", yarn_version)
+            return True
+        return False
+
+
+def tool_version(name):
+    return subprocess.getstatusoutput(name)[1]
+
+
+class EmscriptenTool:
+    def args(self, parser):
+        pass
+
+    def check(self, buildconfig):
+        if existence("emcc"):
+            emscripten_version = tool_version("emcc --version")
+            buildconfig._set_tool("emcc", "emcc", emscripten_version)
+            return True
+        return False
+
+
+class PyBabelTool(Tool):
+    name = "pybabel"
+
+    def args(self, parser):
+        parser.add_argument(
+            "--with-pybabel", type=str, help="name of the pybabel executable"
+        )
+
+    def check(self, buildconfig):
+        # No suffix. Would probably be cheaper to do this in
+        # the dict as well.
+        if existence("pybabel"):
+            buildconfig._set_tool("pybabel", "pybabel")
+            return True
+        else:
+            # Has suffix, try suffix. We know the names in advance,
+            # so use a dictionary and iterate over it. Use enough names
+            # to safe updating this for another couple of years.
+            #
+            # Food for thought: If we only accept python 3.7 or higher,
+            # is checking pybabel + pybabel-3.[0-9]* too much and could
+            # be broken down to pybabel + pybabel-3.7 and later names?
+            version_dict = {
+                "3.0": "pybabel-3.0",
+                "3.1": "pybabel-3.1",
+                "3.2": "pybabel-3.2",
+                "3.3": "pybabel-3.3",
+                "3.4": "pybabel-3.4",
+                "3.5": "pybabel-3.5",
+                "3.6": "pybabel-3.6",
+                "3.7": "pybabel-3.7",
+                "3.8": "pybabel-3.8",
+                "3.9": "pybabel-3.9",
+                "4.0": "pybabel-4.0",
+            }
+            for value in version_dict.values():
+                if existence(value):
+                    buildconfig._set_tool("pybabel", value)
+                    return True
+
+
+class BrowserTool(Tool):
+    name = "browser"
+
+    def args(self, parser):
+        parser.add_argument(
+            "--with-browser", type=str, help="name of your webbrowser 
executable"
+        )
+
+    def check(self, buildconfig):
+        browser_dict = {
+            "ice": "icecat",
+            "ff": "firefox",
+            "chg": "chrome",
+            "ch": "chromium",
+            "o": "opera",
+        }
+        if "BROWSER" in os.environ:
+            buildconfig._set_tool("browser", os.environ["BROWSER"])
+            return True
+        for value in browser_dict.values():
+            if existence(value):
+                buildconfig._set_tool("browser", value)
+                return True
+
+
+class NodeJsTool(Tool):
+    name = "node"
+    hint = "If you are using Ubuntu Linux or Debian Linux, try installing 
the\nnode-legacy package or symlink node to nodejs."
+
+    def args(self, parser):
+        pass
+
+    def check(self, buildconfig):
+        if existence("node") is None:
+            return False
+        if (
+            subprocess.getstatusoutput(
+                "node -p 'process.exit(!(/v([0-9]+)/.exec(process.version)[1] 
>= 4))'"
+            )[1]
+            is not ""
+        ):
+            buildconfig._warn("your node version is too old, use Node 4.x or 
newer")
+            return False
+        node_version = tool_version("node --version")
+        buildconfig._set_tool("node", "node", version=node_version)
+        return True
+
+
+class PosixTool(Tool):
+    def __init__(self, name):
+        self.name = name
+
+    def args(self, parser):
+        pass
+
+    def check(self, buildconfig):
+        found = existence("find")
+        if found:
+            buildconfig._set_tool(self.name, self.name)
+            return True
+        return False
diff --git a/testconfigure.py b/testconfigure.py
new file mode 100644
index 0000000..af7e85a
--- /dev/null
+++ b/testconfigure.py
@@ -0,0 +1,13 @@
+from talerbuildconfig import *
+
+b = BuildConfig()
+b.enable_prefix()
+b.enable_configmk()
+b.add_tool(YarnTool())
+b.add_tool(BrowserTool())
+b.add_tool(PyBabelTool())
+b.add_tool(NodeJsTool())
+b.add_tool(PosixTool("find"))
+b.add_tool(PosixTool("xargs"))
+b.add_tool(PosixTool("msgmerge"))
+b.run()

-- 
To stop receiving notification emails like this one, please contact
address@hidden.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]