diff --git a/bits b/bits index 268740bb..215b54ad 100755 --- a/bits +++ b/bits @@ -224,6 +224,9 @@ do $BITSDIR/bitsBuild $@ exit $? ;; + setenv) + break + ;; *) shift ;; @@ -278,7 +281,7 @@ do --help|help) printHelp; exit 0 ;; -c) - i+=1; COMMAND_IN_ENV=("$@"); + i=$((i+1)); COMMAND_IN_ENV=("${ARGV[@]:${i}}"); break ;; *) ARGS+=(${ARGV[$i]});; diff --git a/bits_helpers/args.py b/bits_helpers/args.py index b3437dd0..5209314c 100644 --- a/bits_helpers/args.py +++ b/bits_helpers/args.py @@ -413,10 +413,7 @@ def finaliseArgs(args, parser): return args if hasattr(args, "defaults"): - if "::" in args.defaults: - args.defaults,args.xdefaults = args.defaults.split("::") - else: - args.xdefaults = None + args.defaults = args.defaults.split("::") # --architecture can be specified in both clean and build. if args.action in ["build", "clean"] and not args.architecture: diff --git a/bits_helpers/build.py b/bits_helpers/build.py index 62b1551c..2685e2de 100644 --- a/bits_helpers/build.py +++ b/bits_helpers/build.py @@ -490,7 +490,7 @@ def doBuild(args, parser): if branch_stream == branch_basename: branch_stream = "" - defaultsReader = lambda : readDefaults(args.configDir, args.defaults, parser.error, args.architecture, args.xdefaults) + defaultsReader = lambda : readDefaults(args.configDir, args.defaults, parser.error, args.architecture) (err, overrides, taps) = parseDefaults(args.disable, defaultsReader, debug) dieOnError(err, err) @@ -876,7 +876,7 @@ def performPreferCheckWithTempDir(pkg, cmd): if possibleDevelPrefix: spec["build_family"] = "%s-%s" % (possibleDevelPrefix, args.defaults) else: - spec["build_family"] = args.defaults + spec["build_family"] = "_".join(args.defaults) if spec["package"] == mainPackage: mainBuildFamily = spec["build_family"] @@ -1176,6 +1176,7 @@ def performPreferCheckWithTempDir(pkg, cmd): if "reference" in spec else ""), ) else: + buildEnvironment = {key: (val if isinstance(val, str) else "_".join(val)) for key, val in buildEnvironment} os.environ.update(buildEnvironment) build_command = "%s -e -x %s/build.sh 2>&1" % (BASH, quote(scriptDir)) @@ -1315,14 +1316,12 @@ def performPreferCheckWithTempDir(pkg, cmd): syncHelper.upload_symlinks_and_tarball(spec) if not args.onlyDeps: - banner("Build of %s successfully completed on `%s'.\n" + banner(f"Build of {mainPackage} successfully completed on `{socket.gethostname()}'.\n" "Your software installation is at:" - "\n\n %s\n\n" + f"\n\n {abspath(join(args.workDir, args.architecture))}\n\n" "You can use this package by loading the environment:" - "\n\n bits enter %s/latest-%s", - mainPackage, socket.gethostname(), - abspath(join(args.workDir, args.architecture)), - mainPackage, mainBuildFamily) + f"\n\n bits enter {mainPackage}/latest-{mainBuildFamily}", + ) else: banner("Successfully built dependencies for package %s on `%s'.\n", mainPackage, socket.gethostname() diff --git a/bits_helpers/deps.py b/bits_helpers/deps.py index 6bff03fc..1eede190 100644 --- a/bits_helpers/deps.py +++ b/bits_helpers/deps.py @@ -14,7 +14,7 @@ def doDeps(args, parser): # Resolve all the package parsing boilerplate specs = {} - defaultsReader = lambda: readDefaults(args.configDir, args.defaults, parser.error, args.architecture, args.xdefaults) + defaultsReader = lambda: readDefaults(args.configDir, args.defaults, parser.error, args.architecture) (err, overrides, taps) = parseDefaults(args.disable, defaultsReader, debug) extra_env = {"BITS_CONFIG_DIR": "/alidist" if args.docker else path.abspath(args.configDir)} diff --git a/bits_helpers/doctor.py b/bits_helpers/doctor.py index ddee9ae0..76f7f889 100644 --- a/bits_helpers/doctor.py +++ b/bits_helpers/doctor.py @@ -134,7 +134,7 @@ def doDoctor(args, parser): systemInfo() specs = {} - defaultsReader = lambda : readDefaults(args.configDir, args.defaults, parser.error, args.architecture, args.xdefaults) + defaultsReader = lambda : readDefaults(args.configDir, args.defaults, parser.error, args.architecture) (err, overrides, taps) = parseDefaults(args.disable, defaultsReader, info) if err: error("%s", err) diff --git a/bits_helpers/init.py b/bits_helpers/init.py index d5d2027b..015984ef 100644 --- a/bits_helpers/init.py +++ b/bits_helpers/init.py @@ -45,7 +45,7 @@ def doInit(args): # Use standard functions supporting overrides and taps. Ignore all disables # and system packages as they are irrelevant in this context specs = {} - defaultsReader = lambda: readDefaults(args.configDir, args.defaults, lambda msg: error("%s", msg), args.architecture, args.xdefaults) + defaultsReader = lambda: readDefaults(args.configDir, args.defaults, lambda msg: error("%s", msg), args.architecture) (err, overrides, taps) = parseDefaults([], defaultsReader, debug) (_,_,_,validDefaults) = getPackageList(packages=[ p["name"] for p in pkgs ], specs=specs, diff --git a/bits_helpers/utilities.py b/bits_helpers/utilities.py index 14a6a3f5..acf13d71 100644 --- a/bits_helpers/utilities.py +++ b/bits_helpers/utilities.py @@ -149,7 +149,7 @@ def resolve_spec_data(spec, data, defaults, branch_basename="", branch_stream="" with the calculated content. """ - defaults_upper = defaults != "release" and "_" + defaults.upper().replace("-", "_") or "" + defaults_upper = "" if defaults == ['release'] else "_".join(d.upper() for d in defaults) commit_hash = spec.get("commit_hash", "hash_unknown") tag = str(spec.get("tag", "tag_unknown")) package = spec.get("package") @@ -333,51 +333,43 @@ def disabledByArchitectureDefaults(arch, defaults, requires): elif not re.match(matcher, arch): yield require - -def merge_ordered_dicts(dict1, dict2): +def merge_dicts(dict1, dict2): """ - Merge two ordered dictionaries where dict2's keys overwrite dict1's keys. - Preserves order with dict1's keys first, followed by dict2's new keys. + Merge two ordered dictionaries where dict2's keys updates dict1's keys recursively. """ - merged = OrderedDict() # Add all keys from dict1 first - for key, value in dict1.items(): - merged[key] = value - + merged = dict1.copy() # Overwrite with dict2's values and add new keys for key, value in dict2.items(): - if key in merged and isinstance(merged[key], OrderedDict) and isinstance(value, OrderedDict): + if key not in merged: + merged[key] = value + continue + elif isinstance(merged[key], dict) and isinstance(value, dict): # Recursively merge nested ordered dictionaries - merged[key] = merge_ordered_dicts(merged[key], value) + merged[key] = merge_dicts(merged[key], value) + elif isinstance(merged[key], list) and isinstance(value, list): + # merge lists, such as for "disabled" + merged[key].extend(value) else: # Overwrite existing key or add new key merged[key] = value return merged - - -def readDefaults(configDir, defaults, error, architecture, xdefaults): - - defaultsFilename = resolveDefaultsFilename(defaults,configDir) - err, defaultsMeta, defaultsBody = parseRecipe(getRecipeReader(defaultsFilename)) - if err: - error(err) - sys.exit(1) - - for x in ["overrides"]: - defaultsMeta[x] = asDict(defaultsMeta.get(x, OrderedDict())) - - debug("Defaults: %s ",json.dumps(defaultsMeta,indent = 4)) - - if xdefaults is not None: + +def readDefaults(configDir, defaults, error, architecture): + defaultsMeta = {} + defaultsBody = "" + + for xdefaults in defaults: xDefaults = resolveDefaultsFilename(xdefaults,configDir) xMeta = {} - xBody = "" if exists(xDefaults): err, xMeta, xBody = parseRecipe(getRecipeReader(xDefaults)) + if xBody.strip() != "": + defaultsBody += "\n" + xBody.strip() if err: error(err) sys.exit(1) - defaultsMeta = merge_ordered_dicts(defaultsMeta, xMeta) + defaultsMeta = merge_dicts(defaultsMeta, xMeta) archDefaults = "%s/defaults-%s.sh" % (configDir, architecture) archMeta = {} @@ -558,26 +550,6 @@ def asDict(overrides_array): debug("asDict (result): %s ",json.dumps(result)) return result -def merge_dicts(dict1, dict2): - """ - Helper function to merge two dictionaries recursively. - dict2 values overwrite dict1 values. - """ - merged = OrderedDict(dict1) - - for key, value in dict2.items(): - if (key in merged and - isinstance(merged[key], dict) and - isinstance(value, dict)): - # Recursively merge nested dictionaries - merged[key] = merge_dicts(merged[key], value) - else: - # Overwrite or add new key-value pair - merged[key] = value - - return merged - - # (Almost pure part of the defaults parsing) # Override defaultsGetter for unit tests. def parseDefaults(disable, defaultsGetter, log): @@ -674,10 +646,18 @@ def getPackageList(packages, specs, configDir, preferSystem, noSystem, packages = packages[:] generatedPackages = getGeneratedPackages(configDir) validDefaults = [] # empty list: all OK; None: no valid default; non-empty list: list of valid ones - while packages: p = packages.pop(0) - if p in specs or (p == "defaults-release" and ("defaults-" + defaults) in specs): + if p in specs: + continue + skip = False + for d in defaults: + if p == "defaults-release" and ("defaults-" + d) in specs: + skip = True + break + else: + pkg_filename = ("defaults-" + d) if p == "defaults-release" else p.lower() + if skip: continue # We rewrite all defaults to "defaults-release", so load the correct @@ -687,8 +667,6 @@ def getPackageList(packages, specs, configDir, preferSystem, noSystem, # they will end up with the same hash. The defaults must be called # "defaults-release" for this to work, since the defaults are a dependency # and all dependencies' names go into a package's hash. - pkg_filename = ("defaults-" + defaults) if p == "defaults-release" else p.lower() - filename,pkgdir = resolveFilename(taps, pkg_filename, configDir, generatedPackages) dieOnError(not filename, "Package %s not found in %s" % (p, configDir)) diff --git a/tests/test_args.py b/tests/test_args.py index d3e2288b..fab0ea54 100644 --- a/tests/test_args.py +++ b/tests/test_args.py @@ -58,10 +58,10 @@ class FakeExit(Exception): ((), "build zlib -a slc7_x86-64 --docker-extra-args=--foo" , [("docker", True), ("dockerImage", "registry.cern.ch/alisw/slc7-builder"), ("docker_extra_args", ["--foo", "--network=host"])]), ((), "build zlib --devel-prefix -a slc7_x86-64 --docker" , [("docker", True), ("dockerImage", "registry.cern.ch/alisw/slc7-builder"), ("develPrefix", "%s-slc7_x86-64" % os.path.basename(os.getcwd()))]), ((), "build zlib --devel-prefix -a slc7_x86-64 --docker-image someimage" , [("docker", True), ("dockerImage", "someimage"), ("develPrefix", "%s-slc7_x86-64" % os.path.basename(os.getcwd()))]), - ((), "--debug build --force-unknown-architecture --defaults o2 O2" , [("debug", True), ("action", "build"), ("defaults", "o2"), ("pkgname", ["O2"])]), - ((), "build --force-unknown-architecture --debug --defaults o2 O2" , [("debug", True), ("action", "build"), ("force_rebuild", []), ("defaults", "o2"), ("pkgname", ["O2"])]), - ((), "build --force-unknown-architecture --force-rebuild O2 --force-rebuild O2Physics --defaults o2 O2Physics", [("action", "build"), ("force_rebuild", ["O2", "O2Physics"]), ("defaults", "o2"), ("pkgname", ["O2Physics"])]), - ((), "build --force-unknown-architecture --force-rebuild O2,O2Physics --defaults o2 O2Physics", [("action", "build"), ("force_rebuild", ["O2", "O2Physics"]), ("defaults", "o2"), ("pkgname", ["O2Physics"])]), + ((), "--debug build --force-unknown-architecture --defaults o2 O2" , [("debug", True), ("action", "build"), ("defaults", ["o2"]), ("pkgname", ["O2"])]), + ((), "build --force-unknown-architecture --debug --defaults o2 O2" , [("debug", True), ("action", "build"), ("force_rebuild", []), ("defaults", ["o2"]), ("pkgname", ["O2"])]), + ((), "build --force-unknown-architecture --force-rebuild O2 --force-rebuild O2Physics --defaults o2 O2Physics", [("action", "build"), ("force_rebuild", ["O2", "O2Physics"]), ("defaults", ["o2"]), ("pkgname", ["O2Physics"])]), + ((), "build --force-unknown-architecture --force-rebuild O2,O2Physics --defaults o2 O2Physics", [("action", "build"), ("force_rebuild", ["O2", "O2Physics"]), ("defaults", ["o2"]), ("pkgname", ["O2Physics"])]), ((), "init -z test zlib" , [("configDir", "test/alidist")]), ((), "build --force-unknown-architecture -z test zlib" , [("configDir", "alidist")]), # ((), "analytics off" , [("state", "off")]), diff --git a/tests/test_build.py b/tests/test_build.py index 017bd8fe..14089916 100644 --- a/tests/test_build.py +++ b/tests/test_build.py @@ -275,7 +275,7 @@ def test_coverDoBuild(self, mock_debug, mock_listdir, mock_warning, mock_git_git configDir="/alidist", disable=[], force_rebuild=[], - defaults="release", + defaults=["release"], jobs=2, annotate={}, preferSystem=[], @@ -291,7 +291,6 @@ def test_coverDoBuild(self, mock_debug, mock_listdir, mock_warning, mock_git_git forceTracked=False, plugin="legacy", makeflow=False, - xdefaults=None ) def mkcall(args): diff --git a/tests/test_deepmergedefaults.py b/tests/test_deepmergedefaults.py new file mode 100644 index 00000000..ea6f5535 --- /dev/null +++ b/tests/test_deepmergedefaults.py @@ -0,0 +1,77 @@ +import unittest +import yaml +import bits_helpers.utilities +from bits_helpers.utilities import merge_dicts + +class DeepMergeTest(unittest.TestCase): + # Test overwriting existing top-level keys from dict1 with top-level keys from dict2. + # Test adding new top level keys from dict2. + def test_flat_merge(self): + d1 = ({"a": 1, "b": 2}) + d2 = ({"b": 3, "c": 4}) + result = merge_dicts(d1, d2) + self.assertEqual(result, {"a": 1, "b": 3, "c": 4}) + + # Test nested merge of dicts within dicts + def test_nested_merge(self): + d1 = { + "a": 1, + "b": {"x": 1, "y": 2}, + } + d2 = { + "b": {"y": 3, "z": 4}, + "c": 5, + } + result = merge_dicts(d1, d2) + expected = {"a": 1, "b": {"x": 1, "y": 3, "z": 4}, "c": 5} + self.assertEqual(result, expected) + + # Test merging of lists + def test_list_merge(self): + d1 = {"disabled": ["pkg1", "pkg2"]} + d2 = {"disabled": ["pkg3"]} + result = merge_dicts(d1, d2) + self.assertEqual(result, {"disabled": ["pkg1", "pkg2", "pkg3"]}) + + # Test non-recursive overwrite on type mismatch between dict and non-dict + def test_overwrite_non_dict(self): + d1 = {"a": {"nested": 1}} + d2 = {"a": 42} + result = merge_dicts(d1, d2) + self.assertEqual(result, {"a": 42}) + + # Test merging of non-overlapping dictionaries + def test_new_key_added(self): + d1 = {"a": 1} + d2 = {"b": 2} + result = merge_dicts(d1, d2) + self.assertEqual(result, {"a": 1, "b": 2}) + + # Test merging of empty dictionaries + def test_empty_dicts(self): + d1 = {} + d2 = {} + result = merge_dicts(d1, d2) + self.assertEqual(result, {}) + + # Test merging a non-empty first with empty second dict + def test_merge_with_empty_second(self): + d1 = {"a": 1} + d2 = {} + result = merge_dicts(d1, d2) + self.assertEqual(result, {"a": 1}) + + # Test merging a empty first with non-empty second dict + def test_merge_with_empty_first(self): + d1 = {} + d2 = {"b": 2} + result = merge_dicts(d1, d2) + self.assertEqual(result, {"b": 2}) + + # Test type mismatch between list and non-list + def test_list_non_list_conflict(self): + """When one side is list and the other is not, prefer dict2.""" + d1 = {"disabled": ["pkg1", "pkg2"]} + d2 = {"disabled": "notalist"} + result = merge_dicts(d1, d2) + self.assertEqual(result, {"disabled": "notalist"}) diff --git a/tests/test_defaultswithinclude.py b/tests/test_defaultswithinclude.py new file mode 100644 index 00000000..8804b5e1 --- /dev/null +++ b/tests/test_defaultswithinclude.py @@ -0,0 +1,174 @@ +import os +import tempfile + +import unittest +import yaml +import bits_helpers.utilities +from bits_helpers.utilities import merge_dicts +from bits_helpers.utilities import yamlLoad + +class TestYamlLoadIncludes(unittest.TestCase): + + def setUp(self): + # Sets up temporary directories + self.tmpdir = tempfile.TemporaryDirectory() + self.dir = self.tmpdir.name + + def tearDown(self): + # Removes temporary directories + self.tmpdir.cleanup() + + def _write(self, name, content): + # Helper to write test files in the temp directory + path = os.path.join(self.dir, name) + with open(path, "w") as f: + f.write(content) + return path + + def test_basic_include(self): + # Include one YAML file inside a defaults file + included = self._write("included.yaml", """ + b: 2 + """) + main = r""" + a: 1 + overrides: !include included.yaml + """ + + with open(os.path.join(self.dir, "main.yaml"), "w") as f: + f.write(main) + + with open(os.path.join(self.dir, "main.yaml")) as f: + data = yamlLoad(f) + + self.assertEqual(data["a"], 1) + self.assertEqual(data["overrides"]["b"], 2) + + def test_nested_includes(self): + # Include a yaml file that itself includes another yaml file in a defaults file + deep = self._write("deep.yaml", """ + x: 42 + """) + inner = self._write("inner.yaml", r""" + nested: !include deep.yaml + """) + main = self._write("main.yaml", r""" + root: !include inner.yaml + """) + + with open(main) as f: + data = yamlLoad(f) + + self.assertEqual(data["root"]["nested"]["x"], 42) + + def test_missing_include_raises(self): + # Include a missing yaml file raises FileNotFoundError + main = self._write("main.yaml", """ + missing: !include nofile.yaml + """) + + with self.assertRaises(FileNotFoundError): + with open(main) as f: + yamlLoad(f) + + def test_relative_path_resolution(self): + # !include paths should be resolved relative to the parent file. + subdir = os.path.join(self.dir, "sub") + os.makedirs(subdir) + included = os.path.join(subdir, "child.yaml") + with open(included, "w") as f: + f.write("v: 99") + main = os.path.join(self.dir, "main.yaml") + with open(main, "w") as f: + f.write("child: !include sub/child.yaml") + + with open(main) as f: + data = yamlLoad(f) + + self.assertEqual(data["child"]["v"], 99) + + def test_order_preservation(self): + included = self._write("included.yaml", r""" + x: 1 + y: 2 + """) + main = self._write("main.yaml", r""" + !include included.yaml + """) + + with open(main) as f: + data = yamlLoad(f) + + keys = list(data.keys()) + self.assertEqual(keys, ["x", "y"]) + + def test_merge_defaults_with_package_overrides(self): + # Simulate a "base defaults" YAML structure + base_defaults = { + "packages": { + "ROOT": { + "tag": "v6-30-04", + "source": "https://github.com/root-project/root.git", + "requires": ["Python", "zlib"], + }, + "AliRoot": { + "tag": "v5-09-60", + "source": "https://github.com/alisw/AliRoot.git", + "requires": ["ROOT"], + }, + }, + "disable": ["MySQL"], + "architecture": "slc9_x86-64", + } + + # Simulate an "override defaults" YAML + override_defaults = { + "packages": { + "ROOT": { + # overrides the tag and adds an extra dependency + "tag": "v6-32-02", + "requires": ["Python", "zlib", "OpenSSL"], + }, + "AliRoot": { + # same tag, but overrides the source + "source": "https://mirror.example.com/AliRoot.git", + }, + "AliPhysics": { + # completely new package + "tag": "v5-09-60a", + "source": "https://github.com/alisw/AliPhysics.git", + "requires": ["AliRoot"], + }, + }, + "disable": ["Boost"], + } + + merged = merge_dicts(base_defaults, override_defaults) + + # Expected result: overrides applied, lists extended, new packages added + expected = { + "packages": { + "ROOT": { + "tag": "v6-32-02", + "source": "https://github.com/root-project/root.git", + "requires": ["Python", "zlib", "OpenSSL"], + }, + "AliRoot": { + "tag": "v5-09-60", + "source": "https://mirror.example.com/AliRoot.git", + "requires": ["ROOT"], + }, + "AliPhysics": { + "tag": "v5-09-60a", + "source": "https://github.com/alisw/AliPhysics.git", + "requires": ["AliRoot"], + }, + }, + "disable": ["MySQL", "Boost"], + "architecture": "slc9_x86-64", + } + + self.assertEqual(merged, expected) + self.assertIn("AliPhysics", merged["packages"]) + self.assertEqual(merged["packages"]["ROOT"]["tag"], "v6-32-02") + self.assertIn("Boost", merged["disable"]) diff --git a/tests/test_deps.py b/tests/test_deps.py index e8b30920..12cd3b1d 100644 --- a/tests/test_deps.py +++ b/tests/test_deps.py @@ -65,15 +65,14 @@ def depsOpen(fn, mode): outdot="/tmp/out.dot", outgraph="/tmp/outgraph.pdf", package="AliRoot", - defaults="release", - environment=[], - xdefaults=None) + defaults=["release"], + environment=[]) + def fake_exists(n): return {"/alidist/aliroot.sh": True} with patch.object(os.path, "exists", fake_exists): doDeps(args, MagicMock()) - def fake_exists(n): return True if n in RECIPES else False diff --git a/tests/test_doctor.py b/tests/test_doctor.py index 11e1ecde..7ca9c1a9 100644 --- a/tests/test_doctor.py +++ b/tests/test_doctor.py @@ -90,9 +90,8 @@ def resetOut(): noSystem="*", architecture="osx_x86-64", disable=[], - defaults="release", - environment=[], - xdefaults=None) + defaults=["release"], + environment=[]) # What to call (longer names deprecated in Python 3.5+) if not hasattr(self, "assertRegex"): diff --git a/tests/test_init.py b/tests/test_init.py index 0522188f..fe3ca519 100644 --- a/tests/test_init.py +++ b/tests/test_init.py @@ -44,12 +44,11 @@ def test_doDryRunInit(self, mock_os, mock_path, mock_info) -> None: pkgname = "zlib,AliRoot@v5-08-00", referenceSources = "/sw/MIRROR", dist = fake_dist, - defaults = "release", + defaults = ["release"], dryRun = True, fetchRepos = False, architecture = "slc7_x86-64", environment = {}, - xdefaults = None ) self.assertRaises(SystemExit, doInit, args) self.assertEqual(mock_info.mock_calls, [call('This will initialise local checkouts for %s\n--dry-run / -n specified. Doing nothing.', 'zlib,AliRoot')]) @@ -85,12 +84,11 @@ def test_doRealInit(self, mock_read_defaults, mock_open, mock_update_reference, pkgname = "AliRoot@v5-08-00", referenceSources = "/sw/MIRROR", dist = fake_dist, - defaults = "release", + defaults = ["release"], dryRun = False, fetchRepos = False, architecture = "slc7_x86-64", environment = {}, - xdefaults = None ) doInit(args) self.assertEqual(mock_git.mock_calls, CLONE_EVERYTHING) diff --git a/tests/test_packagelist.py b/tests/test_packagelist.py index e762f429..a279cd60 100644 --- a/tests/test_packagelist.py +++ b/tests/test_packagelist.py @@ -105,7 +105,7 @@ def performPreferCheckWithTempDir(pkg, cmd): noSystem=None, architecture="ARCH", disable=[], - defaults="release", + defaults=["release"], # Mock recipes just run "echo" or ":", so this is safe. performPreferCheck=performPreferCheckWithTempDir, performRequirementCheck=performPreferCheckWithTempDir, diff --git a/tests/testdist/defaults-release.sh b/tests/testdist/defaults-release.sh new file mode 100644 index 00000000..3153c10b --- /dev/null +++ b/tests/testdist/defaults-release.sh @@ -0,0 +1,10 @@ +package: defaults-release +version: v1 +env: + CXXFLAGS: "-fPIC -g -O2 -std=c++11" + CFLAGS: "-fPIC -g -O2" + CMAKE_BUILD_TYPE: "RELWITHDEBINFO" +--- +# This file is included in any build recipe and it's only used to set +# environment variables. Which file to actually include can be defined by the +# "--defaults" option of bits. diff --git a/tox.ini b/tox.ini index fbeef159..e2cdc813 100644 --- a/tox.ini +++ b/tox.ini @@ -21,6 +21,8 @@ python = ; allowlist_externals = ; find ; deps = +; bison +; flex ; flake8 ; pylint ; changedir = {toxinidir}