Skip to content

Commit

Permalink
Allow specifying a custom output for the deployers (#13757)
Browse files Browse the repository at this point in the history
* Allow specifying a custom output for the deployers

* Rename to --deployer-folder

* Restore mkdir()

* Move mkdir to do_deploys

* Make tests use new --deployer argument (Was --deploy)

* Missed one
  • Loading branch information
AbrilRBS authored Jun 5, 2023
1 parent a8074a2 commit a930709
Show file tree
Hide file tree
Showing 8 changed files with 53 additions and 31 deletions.
6 changes: 2 additions & 4 deletions conan/api/subapi/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
from conans.client.generators import write_generators
from conans.client.installer import BinaryInstaller
from conans.errors import ConanInvalidConfiguration
from conans.util.files import mkdir


class InstallAPI:
Expand Down Expand Up @@ -41,7 +40,7 @@ def install_sources(self, graph, remotes):

# TODO: Look for a better name
def install_consumer(self, deps_graph, generators=None, source_folder=None, output_folder=None,
deploy=False):
deploy=False, deploy_folder=None):
""" Once a dependency graph has been installed, there are things to be done, like invoking
generators for the root consumer.
This is necessary for example for conanfile.txt/py, or for "conan install <ref> -g
Expand All @@ -63,8 +62,7 @@ def install_consumer(self, deps_graph, generators=None, source_folder=None, outp

# The previous .set_base_folders has already decided between the source_folder and output
if deploy:
base_folder = conanfile.folders.base_build
mkdir(base_folder)
base_folder = deploy_folder or conanfile.folders.base_build
do_deploys(self.conan_api, deps_graph, deploy, base_folder)

conanfile.generators = list(set(conanfile.generators).union(generators or []))
Expand Down
5 changes: 3 additions & 2 deletions conan/cli/commands/graph.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import json
import os

from conan.api.output import ConanOutput, cli_out_write, Color
from conan.cli import make_abs_path
from conan.cli.args import common_graph_args, validate_common_graph_args
Expand Down Expand Up @@ -119,6 +118,8 @@ def graph_info(conan_api, parser, subparser, *args):
help='Print information only for packages that match the patterns')
subparser.add_argument("-d", "--deployer", action="append",
help='Deploy using the provided deployer to the output folder')
subparser.add_argument("-df", "--deployer-folder",
help="Deployer output folder, base build folder by default if not set")
subparser.add_argument("--build-require", action='store_true', default=False,
help='Whether the provided reference is a build-require')
args = parser.parse_args(*args)
Expand Down Expand Up @@ -169,7 +170,7 @@ def graph_info(conan_api, parser, subparser, *args):
clean=args.lockfile_clean)
conan_api.lockfile.save_lockfile(lockfile, args.lockfile_out, cwd)
if args.deployer:
base_folder = os.getcwd()
base_folder = args.deployer_folder or os.getcwd()
do_deploys(conan_api, deps_graph, args.deployer, base_folder)

return {"graph": deps_graph,
Expand Down
5 changes: 4 additions & 1 deletion conan/cli/commands/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ def install(conan_api, parser, *args):
help='The root output folder for generated and build files')
parser.add_argument("-d", "--deployer", action="append",
help='Deploy using the provided deployer to the output folder')
parser.add_argument("--deployer-folder",
help="Deployer output folder, base build folder by default if not set")
parser.add_argument("--build-require", action='store_true', default=False,
help='Whether the provided reference is a build-require')
args = parser.parse_args(*args)
Expand Down Expand Up @@ -83,7 +85,8 @@ def install(conan_api, parser, *args):
generators=args.generator,
output_folder=output_folder,
source_folder=source_folder,
deploy=args.deployer
deploy=args.deployer,
deploy_folder=args.deployer_folder
)

out.success("Install finished successfully")
Expand Down
3 changes: 2 additions & 1 deletion conan/internal/deploy.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from conans.client.cache.cache import ClientCache
from conans.client.loader import load_python_file
from conans.errors import ConanException
from conans.util.files import rmdir
from conans.util.files import rmdir, mkdir


def _find_deployer(d, cache_deploy_folder):
Expand Down Expand Up @@ -36,6 +36,7 @@ def _load(path):


def do_deploys(conan_api, graph, deploy, deploy_folder):
mkdir(deploy_folder)
# Handle the deploys
cache = ClientCache(conan_api.cache_folder)
for d in deploy or []:
Expand Down
49 changes: 34 additions & 15 deletions conans/test/functional/command/test_install_deploy.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ def deploy(graph, output_folder, **kwargs):
"main.cpp": gen_function_cpp(name="main", includes=["hello"], calls=["hello"])},
clean_first=True)
c.run("install . -o *:shared=True "
"--deploy=deploy.py -of=mydeploy -g CMakeToolchain -g CMakeDeps")
"--deployer=deploy.py -of=mydeploy -g CMakeToolchain -g CMakeDeps")
c.run("remove * -c") # Make sure the cache is clean, no deps there
arch = c.get_default_host_profile().settings['arch']
deps = c.load(f"mydeploy/hello-release-{arch}-data.cmake")
Expand Down Expand Up @@ -119,7 +119,7 @@ def test_install_full_deploy_layout(client):
"CMakeLists.txt": cmake,
"main.cpp": gen_function_cpp(name="main", includes=["hello"], calls=["hello"])},
clean_first=True)
c.run("install . -o *:shared=True --deploy=full_deploy.py")
c.run("install . -o *:shared=True --deployer=full_deploy.py")
c.run("remove * -c") # Make sure the cache is clean, no deps there
arch = c.get_default_host_profile().settings['arch']
folder = "/Release" if platform.system() != "Windows" else ""
Expand Down Expand Up @@ -166,7 +166,7 @@ def deploy(graph, output_folder, **kwargs):
"hello/conanfile.py": GenConanfile("hello", "0.1").with_package_file("bin/file.txt",
"content!!")})
c.run("create hello")
c.run("install . --deploy=deploy.py -of=mydeploy")
c.run("install . --deployer=deploy.py -of=mydeploy")


def test_multi_deploy():
Expand Down Expand Up @@ -198,13 +198,13 @@ def deploy(graph, output_folder, **kwargs):
"mydeploy.py": deploy1,
"sub/mydeploy2.py": deploy2})

c.run("install . --deploy=mydeploy --deploy=sub/mydeploy2 --deploy=deploy_cache")
c.run("install . --deployer=mydeploy --deployer=sub/mydeploy2 --deployer=deploy_cache")
assert "conanfile.txt: deploy1!!" in c.out
assert "conanfile.txt: sub/deploy2!!" in c.out
assert "conanfile.txt: deploy cache!!" in c.out

# Now with .py extension
c.run("install . --deploy=mydeploy.py --deploy=sub/mydeploy2.py --deploy=deploy_cache.py")
c.run("install . --deployer=mydeploy.py --deployer=sub/mydeploy2.py --deployer=deploy_cache.py")
assert "conanfile.txt: deploy1!!" in c.out
assert "conanfile.txt: sub/deploy2!!" in c.out
assert "conanfile.txt: deploy cache!!" in c.out
Expand All @@ -226,7 +226,7 @@ def deploy(graph, output_folder, **kwargs):
save(os.path.join(c.cache_folder, "extensions", "deployers", "deploy_cache.py"), deploy_cache)
save(os.path.join(c.cache_folder, "extensions", "deployers", "helper.py"), helper)
c.save({"conanfile.txt": ""})
c.run("install . --deploy=deploy_cache")
c.run("install . --deployer=deploy_cache")
assert "conanfile.txt: My HELPER!!" in c.out


Expand All @@ -252,9 +252,9 @@ def package_info(self):
c.run("create . --name=dep --version=0.1")
c.run("create . --name=dep --version=0.1 -s build_type=Debug -s arch=x86")
c.save({"conanfile.txt": "[requires]\ndep/0.1"}, clean_first=True)
c.run("install . --deploy=full_deploy -of=output -g CMakeDeps")
c.run("install . --deployer=full_deploy -of=output -g CMakeDeps")
assert "Conan built-in full deployer" in c.out
c.run("install . --deploy=full_deploy -of=output -g CMakeDeps "
c.run("install . --deployer=full_deploy -of=output -g CMakeDeps "
"-s build_type=Debug -s arch=x86")

host_arch = c.get_default_host_profile().settings['arch']
Expand All @@ -281,14 +281,14 @@ def test_deploy_reference():
c.save({"conanfile.py": GenConanfile("pkg", "1.0").with_package_file("include/hi.h", "hi")})
c.run("create .")

c.run("install --requires=pkg/1.0 --deploy=full_deploy --output-folder=output")
c.run("install --requires=pkg/1.0 --deployer=full_deploy --output-folder=output")
# NOTE: Full deployer always use build_type/arch, even if None/None in the path, same structure
header = c.load("output/full_deploy/host/pkg/1.0/include/hi.h")
assert "hi" in header

# Testing that we can deploy to the current folder too
c.save({}, clean_first=True)
c.run("install --requires=pkg/1.0 --deploy=full_deploy")
c.run("install --requires=pkg/1.0 --deployer=full_deploy")
# NOTE: Full deployer always use build_type/arch, even if None/None in the path, same structure
header = c.load("full_deploy/host/pkg/1.0/include/hi.h")
assert "hi" in header
Expand All @@ -301,14 +301,14 @@ def test_deploy_overwrite():
c.save({"conanfile.py": GenConanfile("pkg", "1.0").with_package_file("include/hi.h", "hi")})
c.run("create .")

c.run("install --requires=pkg/1.0 --deploy=full_deploy --output-folder=output")
c.run("install --requires=pkg/1.0 --deployer=full_deploy --output-folder=output")
header = c.load("output/full_deploy/host/pkg/1.0/include/hi.h")
assert "hi" in header

# modify the package
c.save({"conanfile.py": GenConanfile("pkg", "1.0").with_package_file("include/hi.h", "bye")})
c.run("create .")
c.run("install --requires=pkg/1.0 --deploy=full_deploy --output-folder=output")
c.run("install --requires=pkg/1.0 --deployer=full_deploy --output-folder=output")
header = c.load("output/full_deploy/host/pkg/1.0/include/hi.h")
assert "bye" in header

Expand All @@ -325,7 +325,7 @@ def test_deploy_editable():

# If we don't change to another folder, the full_deploy will be recursive and fail
with c.chdir(temp_folder()):
c.run("install --requires=pkg/1.0 --deploy=full_deploy --output-folder=output")
c.run("install --requires=pkg/1.0 --deployer=full_deploy --output-folder=output")
header = c.load("output/full_deploy/host/pkg/1.0/src/include/hi.h")
assert "hi" in header

Expand All @@ -339,11 +339,30 @@ def test_deploy_single_package():
c.run("create .")

# if we deploy one --requires, we get that package
c.run("install --requires=pkg/1.0 --deploy=direct_deploy --output-folder=output")
c.run("install --requires=pkg/1.0 --deployer=direct_deploy --output-folder=output")
header = c.load("output/direct_deploy/pkg/include/hi.h")
assert "hi" in header

# If we deploy a local conanfile.txt, we get deployed its direct dependencies
c.run("install consumer/conanfile.txt --deploy=direct_deploy --output-folder=output2")
c.run("install consumer/conanfile.txt --deployer=direct_deploy --output-folder=output2")
header = c.load("output2/direct_deploy/pkg/include/hi.h")
assert "hi" in header


def test_deploy_output_locations():
tc = TestClient()
deployer = textwrap.dedent("""
def deploy(graph, output_folder, **kwargs):
graph.root.conanfile.output.info(f"Deployer output: {output_folder}")
""")
tc.save({"conanfile.txt": "",
"my_deploy.py": deployer})

tmp_folder = temp_folder()
tc.run(f"install . --deployer=my_deploy -of='{tmp_folder}'")
assert f"Deployer output: {tmp_folder}" in tc.out

deployer_output = temp_folder()
tc.run(f"install . --deployer=my_deploy -of='{tmp_folder}' --deployer-folder='{deployer_output}'")
assert f"Deployer output: {deployer_output}" in tc.out
assert f"Deployer output: {tmp_folder}" not in tc.out
4 changes: 2 additions & 2 deletions conans/test/functional/toolchains/cmake/test_ninja.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def test_locally_build_linux(build_type, shared, client):
client.run("create . --name=hello --version=1.0 {}".format(settings))
assert 'cmake -G "Ninja"' in client.out
assert "main: {}!".format(build_type) in client.out
client.run(f"install --requires=hello/1.0@ --deploy=full_deploy -of=mydeploy {settings}")
client.run(f"install --requires=hello/1.0@ --deployer=full_deploy -of=mydeploy {settings}")
deploy_path = os.path.join(client.current_folder, "mydeploy", "full_deploy", "host", "hello", "1.0",
build_type, "x86_64")
client.run_command(f"LD_LIBRARY_PATH='{deploy_path}/lib' {deploy_path}/bin/myapp")
Expand Down Expand Up @@ -111,7 +111,7 @@ def test_locally_build_msvc(build_type, shared, client):
client.run("create . --name=hello --version=1.0 {}".format(settings))
assert 'cmake -G "Ninja"' in client.out
assert "main: {}!".format(build_type) in client.out
client.run(f"install --requires=hello/1.0@ --deploy=full_deploy -of=mydeploy {settings}")
client.run(f"install --requires=hello/1.0@ --deployer=full_deploy -of=mydeploy {settings}")
client.run_command(fr"mydeploy\full_deploy\host\hello\1.0\{build_type}\x86_64\bin\myapp.exe")
check_exe_run(client.out, ["main", "hello"], "msvc", "19", build_type, "x86_64", cppstd="14")

Expand Down
2 changes: 1 addition & 1 deletion conans/test/integration/command/info/info_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ def deploy(graph, output_folder, **kwargs):
c.save({"conanfile.py": GenConanfile().with_requires("pkg/0.1")
.with_class_attribute("license='GPL'"),
"collectlicenses.py": collectlicenses})
c.run("graph info . --deploy=collectlicenses")
c.run("graph info . --deployer=collectlicenses")
assert "conanfile.py: LICENSE : GPL!" in c.out
assert "LICENSE pkg/0.1: MIT!" in c.out
contents = c.load("licenses.txt")
Expand Down
10 changes: 5 additions & 5 deletions conans/test/integration/symlinks/symlinks_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def checker(folder):
c.run("upload * -r=default -c")
c.run("remove * -c")
c.save({}, clean_first=True)
c.run("install --requires=hello/0.1 --deploy=full_deploy")
c.run("install --requires=hello/0.1 --deployer=full_deploy")
checker(os.path.join(c.current_folder, "full_deploy", "host", "hello", "0.1"))


Expand Down Expand Up @@ -89,7 +89,7 @@ def checker(folder):
c.run("upload * -r=default -c")
c.run("remove * -c")
c.save({}, clean_first=True)
c.run("install --requires=hello/0.1 --deploy=full_deploy")
c.run("install --requires=hello/0.1 --deployer=full_deploy")
checker(os.path.join(c.current_folder, "full_deploy", "host", "hello", "0.1"))


Expand Down Expand Up @@ -126,7 +126,7 @@ def checker(folder):
c.run("upload * -r=default -c")
c.run("remove * -c")
c.save({}, clean_first=True)
c.run("install --requires=hello/0.1 --deploy=full_deploy")
c.run("install --requires=hello/0.1 --deployer=full_deploy")
checker(os.path.join(c.current_folder, "full_deploy", "host", "hello", "0.1"))


Expand Down Expand Up @@ -171,7 +171,7 @@ def checker(folder):
c.run("upload * -r=default -c")
c.run("remove * -c")
c.save({}, clean_first=True)
c.run("install --requires=hello/0.1 --deploy=full_deploy")
c.run("install --requires=hello/0.1 --deployer=full_deploy")
checker(os.path.join(c.current_folder, "full_deploy", "host", "hello", "0.1"))


Expand Down Expand Up @@ -228,7 +228,7 @@ def assert_folder_symlinks(base_folder):
client.run("remove * -c")

# Client 2 install
client2.run("install --requires=hello/0.1 --deploy=full_deploy")
client2.run("install --requires=hello/0.1 --deployer=full_deploy")
# Check package files are there
package_folder = client2.get_latest_pkg_layout(pref).package()
assert_folder_symlinks(package_folder)
Expand Down

0 comments on commit a930709

Please sign in to comment.