Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exclude a package when building all from sources #8483

Merged
merged 19 commits into from Apr 20, 2021
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions conans/client/command.py
Expand Up @@ -58,6 +58,8 @@ def __call__(self, parser, namespace, values, option_strings=None): # @UnusedVa
dest.extend(values)
except ValueError:
dest.append(values)
elif hasattr(namespace, "build") and values is None:
dest.append('')


class OnceArgument(argparse.Action):
Expand Down
2 changes: 1 addition & 1 deletion conans/client/graph/build_mode.py
Expand Up @@ -24,7 +24,7 @@ def __init__(self, params, output):
return

assert isinstance(params, list)
if len(params) == 0:
if len(params) == 0 or "*" in params or "" in params:
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If --build, --build= or --build=* is passed, build ALL from sources.

self.all = True
else:
for param in params:
Expand Down
70 changes: 70 additions & 0 deletions conans/test/functional/graph/test_skip_build_install.py
@@ -0,0 +1,70 @@
import pytest
from conans.test.assets.genconanfile import GenConanfile
from conans.test.utils.tools import TestClient


@pytest.fixture(scope="module")
def build_all():
""" Build a simple graph to test --build option

foobar <- bar <- foo
<--------|

All packages are built from sources to keep a cache.
:return: TestClient instance
"""
client = TestClient()
client.save({"conanfile.py": GenConanfile().with_setting("build_type")})
client.run("export . foo/1.0@user/testing")
client.save({"conanfile.py": GenConanfile().with_require("foo/1.0@user/testing")
.with_setting("build_type")})
client.run("export . bar/1.0@user/testing")
client.save({"conanfile.py": GenConanfile().with_require("foo/1.0@user/testing")
.with_require("bar/1.0@user/testing")
.with_setting("build_type")})
client.run("export . foobar/1.0@user/testing")
client.run("install foobar/1.0@user/testing --build")

return client


def test_install_build_single(build_all):
""" When only --build=<ref> is passed, only <ref> must be built
"""
build_all.run("install foobar/1.0@user/testing --build=foo")

assert "bar/1.0@user/testing:7839863d5a059fc6579f28026763e1021268c55e - Cache" in build_all.out
assert "foo/1.0@user/testing:4024617540c4f240a6a5e8911b0de9ef38a11a72 - Build" in build_all.out
assert "foobar/1.0@user/testing:89636fbae346e3983af2dd63f2c5246505e74be7 - Cache" in build_all.out


def test_install_build_double(build_all):
""" When both --build=<ref1> and --build=<ref2> are passed, only both should be built
"""
build_all.run("install foobar/1.0@user/testing --build=foo --build=bar")

assert "bar/1.0@user/testing:7839863d5a059fc6579f28026763e1021268c55e - Build" in build_all.out
assert "foo/1.0@user/testing:4024617540c4f240a6a5e8911b0de9ef38a11a72 - Build" in build_all.out
assert "foobar/1.0@user/testing:89636fbae346e3983af2dd63f2c5246505e74be7 - Cache" in build_all.out


@pytest.mark.parametrize("build_arg", ["--build", "--build=", "--build=*"])
def test_install_build_asterisk(build_arg, build_all):
""" When only --build is passed, all packages must be built from sources
"""
build_all.run("install foobar/1.0@user/testing {}".format(build_arg))

assert "bar/1.0@user/testing:7839863d5a059fc6579f28026763e1021268c55e - Build" in build_all.out
assert "foo/1.0@user/testing:4024617540c4f240a6a5e8911b0de9ef38a11a72 - Build" in build_all.out
assert "foobar/1.0@user/testing:89636fbae346e3983af2dd63f2c5246505e74be7 - Build" in build_all.out


@pytest.mark.parametrize("build_arg", ["--build", "--build=", "--build=*"])
def test_install_build_all_with_single(build_arg, build_all):
""" When --build is passed with another package, all packages must be built from sources.
"""
build_all.run("install foobar/1.0@user/testing --build=foo {}".format(build_arg))

assert "bar/1.0@user/testing:7839863d5a059fc6579f28026763e1021268c55e - Build" in build_all.out
assert "foo/1.0@user/testing:4024617540c4f240a6a5e8911b0de9ef38a11a72 - Build" in build_all.out
assert "foobar/1.0@user/testing:89636fbae346e3983af2dd63f2c5246505e74be7 - Build" in build_all.out
41 changes: 41 additions & 0 deletions conans/test/unittests/client/graph/build_mode_test.py
@@ -1,4 +1,5 @@
import unittest
from parameterized import parameterized

import six

Expand Down Expand Up @@ -33,6 +34,27 @@ def test_valid_params(self):
self.assertFalse(build_mode.never)
self.assertTrue(build_mode.cascade)

build_mode = BuildMode([""], self.output)
self.assertFalse(build_mode.outdated)
self.assertFalse(build_mode.missing)
self.assertFalse(build_mode.never)
self.assertFalse(build_mode.cascade)
self.assertTrue(build_mode.all)

build_mode = BuildMode(["*"], self.output)
self.assertFalse(build_mode.outdated)
self.assertFalse(build_mode.missing)
self.assertFalse(build_mode.never)
self.assertFalse(build_mode.cascade)
self.assertTrue(build_mode.all)

build_mode = BuildMode(["*", "missing"], self.output)
self.assertFalse(build_mode.outdated)
self.assertFalse(build_mode.missing)
self.assertFalse(build_mode.never)
self.assertFalse(build_mode.cascade)
self.assertTrue(build_mode.all)

def test_invalid_configuration(self):
for mode in ["outdated", "missing", "cascade"]:
with six.assertRaisesRegex(self, ConanException,
Expand Down Expand Up @@ -102,6 +124,9 @@ def test_allowed(self):
build_mode = BuildMode([], self.output)
self.assertFalse(build_mode.allowed(self.conanfile))

build_mode = BuildMode(["*"], self.output)
self.assertFalse(build_mode.allowed(self.conanfile))

def test_casing(self):
reference = ConanFileReference.loads("Boost/1.69.0@user/stable")

Expand Down Expand Up @@ -170,3 +195,19 @@ def test_pattern_matching(self):

build_mode.report_matches()
self.assertEqual("", self.output)

@parameterized.expand([((["foo", ""]),), ((["foo", "*"]),), (([""]),), ((["*"]),)])
def test_build_all_and_single(self, build_mode_param):
""" When --build= is present, all packages must be built. It doesn't matter if another
package is listed too.
:param build_mode_param:
:return:
"""
reference = ConanFileReference.loads("foo/0.1@user/stable")
build_mode = BuildMode(build_mode_param, self.output)
self.assertTrue(build_mode.forced(self.conanfile, reference))
self.assertFalse(build_mode.outdated)
self.assertFalse(build_mode.missing)
self.assertFalse(build_mode.never)
self.assertFalse(build_mode.cascade)
self.assertTrue(build_mode.all)