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

Update build local development flow #8589

Merged
merged 32 commits into from
Mar 8, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 2 additions & 12 deletions conans/client/cmd/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,15 @@
from conans.util.log import logger


def cmd_build(app, conanfile_path, source_folder, build_folder, package_folder, install_folder,
test=False, should_configure=True, should_build=True, should_install=True,
def cmd_build(app, conanfile_path, conan_file, source_folder, build_folder, package_folder,
install_folder, test=False, should_configure=True, should_build=True, should_install=True,
should_test=True):
""" Call to build() method saved on the conanfile.py
param conanfile_path: path to a conanfile.py
"""
logger.debug("BUILD: folder '%s'" % build_folder)
logger.debug("BUILD: Conanfile at '%s'" % conanfile_path)

try:
conan_file = app.graph_manager.load_consumer_conanfile(conanfile_path, install_folder,
deps_info_required=True, test=test)
except NotFoundException:
# TODO: Auto generate conanfile from requirements file
raise ConanException("'%s' file is needed for build.\n"
"Create a '%s' and move manually the "
"requirements and generators from '%s' file"
% (CONANFILE, CONANFILE, CONANFILE_TXT))

if test:
try:
conan_file.requires.add_ref(test)
Expand Down
23 changes: 12 additions & 11 deletions conans/client/cmd/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,18 @@ def install_build_and_test(app, conanfile_abs_path, reference, graph_info,
if build_modes is None:
build_modes = ["never"]
try:
deps_install(app=app,
create_reference=reference,
ref_or_path=conanfile_abs_path,
install_folder=test_build_folder,
remotes=remotes,
graph_info=graph_info,
update=update,
build_modes=build_modes,
keep_build=keep_build,
recorder=recorder)
cmd_build(app, conanfile_abs_path, base_folder, test_build_folder,
deps_info = deps_install(app=app,
create_reference=reference,
ref_or_path=conanfile_abs_path,
install_folder=test_build_folder,
remotes=remotes,
graph_info=graph_info,
update=update,
build_modes=build_modes,
keep_build=keep_build,
recorder=recorder)
conanfile = deps_info.root.conanfile
cmd_build(app, conanfile_abs_path, conanfile, base_folder, test_build_folder,
package_folder=os.path.join(test_build_folder, "package"),
install_folder=test_build_folder, test=reference)
finally:
Expand Down
130 changes: 96 additions & 34 deletions conans/client/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -809,49 +809,98 @@ def build(self, *args):
prog="conan build",
formatter_class=SmartFormatter)
parser.add_argument("path", help=_PATH_HELP)
parser.add_argument("-b", "--build", default=None, action="store_true",
help="Execute the build step (variable should_build=True). When "
"specified, configure/install/test won't run unless "
"--configure/--install/--test specified")
parser.add_argument("--name", action=OnceArgument, help='Provide a package name '
'if not specified in conanfile')
parser.add_argument("--version", action=OnceArgument, help='Provide a package version '
'if not specified in conanfile')
parser.add_argument("--user", action=OnceArgument, help='Provide a user')
parser.add_argument("--channel", action=OnceArgument, help='Provide a channel')
parser.add_argument("-bf", "--build-folder", action=OnceArgument, help=_BUILD_FOLDER_HELP)
parser.add_argument("-c", "--configure", default=None, action="store_true",
parser.add_argument("--should_build", default=None, action="store_true",
help="Execute the build step (variable should_build=True). When "
"specified, configure/install/test won't run unless "
"--configure/--install/--test specified")
parser.add_argument("--should_configure", default=None, action="store_true",
help="Execute the configuration step (variable should_configure=True). "
"When specified, build/install/test won't run unless "
"--build/--install/--test specified")
parser.add_argument("-i", "--install", default=None, action="store_true",
"When specified, build/install/test won't run unless "
"--build/--install/--test specified")
parser.add_argument("--should_install", default=None, action="store_true",
help="Execute the install step (variable should_install=True). When "
"specified, configure/build/test won't run unless "
"--configure/--build/--test specified")
parser.add_argument("-t", "--test", default=None, action="store_true",
"specified, configure/build/test won't run unless "
"--configure/--build/--test specified")
parser.add_argument("--should_test", default=None, action="store_true",
help="Execute the test step (variable should_test=True). When "
"specified, configure/build/install won't run unless "
"--configure/--build/--install specified")
parser.add_argument("-if", "--install-folder", action=OnceArgument,
help=_INSTALL_FOLDER_HELP)
"specified, configure/build/install won't run unless "
"--configure/--build/--install specified")
parser.add_argument("-pf", "--package-folder", action=OnceArgument,
help="Directory to install the package (when the build system or "
"build() method does it). Defaulted to the '{build_folder}/package' "
"folder. A relative path can be specified, relative to the current "
"folder. Also an absolute path is allowed.")
"build() method does it). Defaulted to the '{build_folder}/package' "
"folder. A relative path can be specified, relative to the current "
"folder. Also an absolute path is allowed.")
parser.add_argument("-sf", "--source-folder", action=OnceArgument, help=_SOURCE_FOLDER_HELP)

parser.add_argument("-g", "--generator", nargs=1, action=Extender,
help='Generators to use')

parser.add_argument("-if", "--install-folder", action=OnceArgument,
help='Use this directory as the directory where to put the generator'
'files. e.g., conaninfo/conanbuildinfo.txt')

parser.add_argument("--no-imports", action='store_true', default=False,
help='Install specified packages but avoid running imports')
parser.add_argument("-j", "--json", default=None, action=OnceArgument,
help='Path to a json file where the install information will be '
'written')

_add_common_install_arguments(parser, build_help=_help_build_policies.format("never"))
parser.add_argument("--lockfile-node-id", action=OnceArgument,
help="NodeID of the referenced package in the lockfile")

args = parser.parse_args(*args)
self._check_lockfile_args(args)

profile_build = ProfileData(profiles=args.profile_build, settings=args.settings_build,
options=args.options_build, env=args.env_build)

self._warn_python_version()

if args.build or args.configure or args.install or args.test:
build, config, install, test = (bool(args.build), bool(args.configure),
bool(args.install), bool(args.test))
if args.should_build or args.should_configure or args.should_install or args.should_test:
should_build, should_config, should_install, should_test = \
(bool(args.should_build), bool(args.should_configure), bool(args.should_install),
bool(args.should_test))
else:
build = config = install = test = True
return self._conan.build(conanfile_path=args.path,
source_folder=args.source_folder,
package_folder=args.package_folder,
build_folder=args.build_folder,
install_folder=args.install_folder,
should_configure=config,
should_build=build,
should_install=install,
should_test=test)
should_build = should_config = should_install = should_test = True

info = None
try:
info = self._conan.build(conanfile_path=args.path,
name=args.name,
version=args.version,
user=args.user,
channel=args.channel,
source_folder=args.source_folder,
package_folder=args.package_folder,
build_folder=args.build_folder,
install_folder=args.install_folder,
should_configure=should_config,
should_build=should_build,
should_install=should_install,
should_test=should_test,
settings=args.settings_host, options=args.options_host,
env=args.env_host, profile_names=args.profile_host,
profile_build=profile_build,
remote_name=args.remote,
build=args.build,
update=args.update, generators=args.generator,
no_imports=args.no_imports,
lockfile=args.lockfile,
lockfile_out=args.lockfile_out)
except ConanException as exc:
info = exc.info
raise
finally:
if args.json and info:
self._outputer.json_output(info, args.json, os.getcwd())

def package(self, *args):
"""
Expand Down Expand Up @@ -906,20 +955,23 @@ def imports(self, *args):
conanbuildinfo.txt generated file in the --install-folder (defaulted to
the current directory).
"""

parser = argparse.ArgumentParser(description=self.imports.__doc__,
prog="conan imports",
formatter_class=SmartFormatter)
parser.add_argument("path",
help=_PATH_HELP + " With --undo option, this parameter is the folder "
"containing the conan_imports_manifest.txt file generated in a previous"
" execution. e.g.: conan imports ./imported_files --undo ")
parser.add_argument("-if", "--install-folder", action=OnceArgument,
help=_INSTALL_FOLDER_HELP)
parser.add_argument("-imf", "--import-folder", action=OnceArgument,
help="Directory to copy the artifacts to. By default it will be the"
" current directory")
parser.add_argument("-u", "--undo", default=False, action="store_true",
help="Undo imports. Remove imported files")
parser.add_argument("-l", "--lockfile", action=OnceArgument,
help="Path to a lockfile")
_add_profile_arguments(parser)

args = parser.parse_args(*args)

if args.undo:
Expand All @@ -932,7 +984,17 @@ def imports(self, *args):
except ConanException:
pass
self._warn_python_version()
return self._conan.imports(args.path, args.import_folder, args.install_folder)

profile_build = ProfileData(profiles=args.profile_build, settings=args.settings_build,
options=args.options_build, env=args.env_build)

self._warn_python_version()

self._conan.imports(args.path,
args.import_folder, settings=args.settings_host,
options=args.options_host, env=args.env_host,
profile_names=args.profile_host, profile_build=profile_build,
lockfile=args.lockfile)

def export_pkg(self, *args):
"""
Expand Down
87 changes: 73 additions & 14 deletions conans/client/conan_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -719,22 +719,65 @@ def info(self, reference_or_path, remote_name=None, settings=None, options=None,
return deps_graph, deps_graph.root.conanfile

@api_method
def build(self, conanfile_path, source_folder=None, package_folder=None, build_folder=None,
def build(self, conanfile_path, name=None, version=None, user=None, channel=None,
source_folder=None, package_folder=None, build_folder=None,
install_folder=None, should_configure=True, should_build=True, should_install=True,
should_test=True, cwd=None):
self.app.load_remotes()
should_test=True, cwd=None, settings=None, options=None, env=None,
remote_name=None, build=None, profile_names=None,
update=False, generators=None, no_imports=False,
lockfile=None, lockfile_out=None, profile_build=None):

profile_host = ProfileData(profiles=profile_names, settings=settings, options=options, env=env)
recorder = ActionRecorder()
cwd = cwd or os.getcwd()

conanfile_path = _get_conanfile_path(conanfile_path, cwd, py=True)
build_folder = _make_abs_path(build_folder, cwd)
install_folder = _make_abs_path(install_folder, cwd, default=build_folder)
source_folder = _make_abs_path(source_folder, cwd, default=os.path.dirname(conanfile_path))
default_pkg_folder = os.path.join(build_folder, "package")
package_folder = _make_abs_path(package_folder, cwd, default=default_pkg_folder)

cmd_build(self.app, conanfile_path,
source_folder, build_folder, package_folder, install_folder,
should_configure=should_configure, should_build=should_build,
should_install=should_install, should_test=should_test)
try:
lockfile = _make_abs_path(lockfile, cwd) if lockfile else None
graph_info = get_graph_info(profile_host, profile_build, cwd, None,
self.app.cache, self.app.out,
name=name, version=version, user=user, channel=channel,
lockfile=lockfile)

install_folder = _make_abs_path(install_folder, cwd)

remotes = self.app.load_remotes(remote_name=remote_name, update=update)

deps_info = deps_install(app=self.app,
ref_or_path=conanfile_path,
install_folder=install_folder,
remotes=remotes,
graph_info=graph_info,
build_modes=build,
update=update,
generators=generators,
no_imports=no_imports,
recorder=recorder)

if lockfile_out:
lockfile_out = _make_abs_path(lockfile_out, cwd)
graph_lock_file = GraphLockFile(graph_info.profile_host, graph_info.profile_build,
graph_info.graph_lock)
graph_lock_file.save(lockfile_out)

conanfile = deps_info.root.conanfile

cmd_build(self.app, conanfile_path, conanfile,
source_folder, build_folder, package_folder, install_folder,
should_configure=should_configure, should_build=should_build,
should_install=should_install, should_test=should_test)

return recorder.get_info()
except ConanException as exc:
recorder.error = True
exc.info = recorder.get_info()
raise

@api_method
def package(self, path, build_folder, package_folder, source_folder=None, install_folder=None,
Expand Down Expand Up @@ -783,7 +826,8 @@ def source(self, path, source_folder=None, info_folder=None, cwd=None):
config_source_local(conanfile, conanfile_path, self.app.hook_manager)

@api_method
def imports(self, path, dest=None, info_folder=None, cwd=None):
def imports(self, conanfile_path, dest=None, info_folder=None, cwd=None, settings=None,
options=None, env=None, profile_names=None, profile_build=None, lockfile=None):
"""
:param path: Path to the conanfile
:param dest: Dir to put the imported files. (Abs path or relative to cwd)
Expand All @@ -794,13 +838,28 @@ def imports(self, path, dest=None, info_folder=None, cwd=None):
cwd = cwd or os.getcwd()
info_folder = _make_abs_path(info_folder, cwd)
dest = _make_abs_path(dest, cwd)

self.app.load_remotes()
mkdir(dest)
conanfile_abs_path = _get_conanfile_path(path, cwd, py=None)
conanfile = self.app.graph_manager.load_consumer_conanfile(conanfile_abs_path, info_folder,
deps_info_required=True)
run_imports(conanfile, dest)
profile_host = ProfileData(profiles=profile_names, settings=settings, options=options, env=env)
conanfile_path = _get_conanfile_path(conanfile_path, cwd, py=None)
recorder = ActionRecorder()
try:
lockfile = _make_abs_path(lockfile, cwd) if lockfile else None
graph_info = get_graph_info(profile_host, profile_build, cwd, None,
self.app.cache, self.app.out, lockfile=lockfile)

remotes = self.app.load_remotes(remote_name=None, update=False)
deps_info = deps_install(app=self.app,
ref_or_path=conanfile_path,
install_folder=info_folder,
graph_info=graph_info,
recorder=recorder,
remotes=remotes)
conanfile = deps_info.root.conanfile
return run_imports(conanfile, dest)
except ConanException as exc:
recorder.error = True
exc.info = recorder.get_info()
raise

@api_method
def imports_undo(self, manifest_path):
Expand Down
Loading