diff --git a/.travis.yml b/.travis.yml index dfa9bc5791..22428fed2c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,7 +27,7 @@ install: script: - flake8 . - - py.test --cov conda_build --cov-report xml tests + - py.test -v --cov conda_build --cov-report xml tests - conda build --help notifications: diff --git a/appveyor.yml b/appveyor.yml index 712381ec52..3944e7d92b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -78,7 +78,7 @@ build: false test_script: - set "PATH=%CONDA_ROOT%;%CONDA_ROOT%\Scripts;%CONDA_ROOT%\Library\bin;%PATH%" - set PATH - - py.test --cov conda_build --cov-report xml tests + - py.test -v --cov conda_build --cov-report xml tests on_success: - pip install codecov diff --git a/conda_build/build.py b/conda_build/build.py index dbf1bda9dd..2f13770b8f 100644 --- a/conda_build/build.py +++ b/conda_build/build.py @@ -29,7 +29,7 @@ from conda.resolve import Resolve, MatchSpec, NoPackagesFound from conda_build import __version__ -from conda_build import environ, source, tarcheck +from conda_build import environ, source, tarcheck, external from conda_build.config import config from conda_build.render import parse_or_try_download, output_yaml, bldpkg_path from conda_build.scripts import create_entry_points, prepend_bin_path @@ -472,12 +472,23 @@ def build(m, post=None, include_recipe=True, keep_old_work=False, # have the appropriate VCS available in the environment. People # are not used to explicitly listing it in recipes, though. # We add it for them here, but warn them about it. - vcs_source = m.uses_vcs() + vcs_source = m.uses_vcs_in_build() if vcs_source and vcs_source not in specs: - specs.append(vcs_source) - log.warn("Your recipe depends on {} at build time (for templates), " - "but you have not listed it as a build dependency. Doing so for" - " this build.") + vcs_executable = "hg" if vcs_source == "mercurial" else vcs_source + has_vcs_available = os.path.isfile(external.find_executable(vcs_executable)) + if not has_vcs_available: + if (vcs_source != "mercurial" or + not any(spec.startswith('python') and "3." in spec + for spec in specs)): + specs.append(vcs_source) + + log.warn("Your recipe depends on {} at build time (for templates), " + "but you have not listed it as a build dependency. Doing " + "so for this build.") + else: + raise ValueError("Your recipe uses mercurial in build, but mercurial" + " does not yet support Python 3. Please handle all of " + "your mercurial actions outside of your build script.") # Display the name only # Version number could be missing due to dependency on source info. create_env(config.build_prefix, specs) diff --git a/conda_build/main_build.py b/conda_build/main_build.py index 78aecf239f..91cf2bc30b 100644 --- a/conda_build/main_build.py +++ b/conda_build/main_build.py @@ -345,6 +345,10 @@ def execute(args, parser): pkg = line.lstrip(' - ').split(' -> ')[-1] pkg = pkg.strip().split(' ')[0] if pkg in skip_names: + sys.stderr.write("Warning: package conflict - you may have unresolved " + "dependencies. Try to conda install each of your " + "dependencies to figure out which has unresolved " + "dependencies.") continue recipe_glob = glob(pkg + '-[v0-9][0-9.]*') if os.path.exists(pkg): diff --git a/conda_build/metadata.py b/conda_build/metadata.py index b302624e03..56eb7f011a 100644 --- a/conda_build/metadata.py +++ b/conda_build/metadata.py @@ -29,6 +29,8 @@ from conda_build.config import config from conda_build.utils import comma_join +on_win = (sys.platform == 'win32') + def ns_cfg(): # Remember to update the docs of any of this changes @@ -695,7 +697,7 @@ def __repr__(self): ''' return self.__str__() - def uses_vcs(self): + def uses_vcs_in_meta(self): """returns true if recipe contains metadata associated with version control systems. If this metadata is present, a download/copy will be forced in parse_or_try_download. """ @@ -719,3 +721,18 @@ def uses_vcs(self): vcs = "mercurial" return vcs return None + + def uses_vcs_in_build(self): + build_script = "bld.bat" if on_win else "build.sh" + build_script = os.path.join(os.path.dirname(self.meta_path), build_script) + if os.path.isfile(build_script): + vcs_types = ["git", "svn", "hg"] + with open(self.meta_path) as f: + build_script = f.read() + for vcs in vcs_types: + matches = re.findall(r"{}(?:\.exe)?".format(vcs), build_script) + if len(matches) > 0: + if vcs == "hg": + vcs = "mercurial" + return vcs + return None diff --git a/conda_build/render.py b/conda_build/render.py index f048990abe..04afaa9b4b 100644 --- a/conda_build/render.py +++ b/conda_build/render.py @@ -13,7 +13,6 @@ import tempfile import os from os.path import isdir, isfile, abspath -import re import subprocess import yaml @@ -78,7 +77,7 @@ def bldpkg_path(m): def parse_or_try_download(metadata, no_download_source, verbose, force_download=False, dirty=False): - if (force_download or (not no_download_source and metadata.uses_vcs())): + if (force_download or (not no_download_source and metadata.uses_vcs_in_meta())): # this try/catch is for when the tool to download source is actually in # meta.yaml, and not previously installed in builder env. try: @@ -93,6 +92,8 @@ def parse_or_try_download(metadata, no_download_source, verbose, print("Error was: ") print(error) need_source_download = True + elif not metadata.get_section('source'): + need_source_download = False else: # we have not downloaded source in the render phase. Download it in # the build phase diff --git a/conda_build/windows.py b/conda_build/windows.py index b07daeee79..d224999dc9 100644 --- a/conda_build/windows.py +++ b/conda_build/windows.py @@ -20,6 +20,12 @@ assert sys.platform == 'win32' +# Set up a load of paths that can be imported from the tests +if 'ProgramFiles(x86)' in os.environ: + PROGRAM_FILES_PATH = os.environ['ProgramFiles(x86)'] +else: + PROGRAM_FILES_PATH = os.environ['ProgramFiles'] + WIN_SDK_71_PATH = Reg.get_value(os.path.join(WINSDK_BASE, 'v7.1'), 'installationfolder') WIN_SDK_71_BAT_PATH = os.path.join(WIN_SDK_71_PATH, 'Bin', 'SetEnv.cmd') @@ -69,6 +75,22 @@ def fix_staged_scripts(): os.remove(join(scripts_dir, fn)) +def build_vcvarsall_vs_path(version): + """ + Given the Visual Studio version, returns the default path to the + Microsoft Visual Studio vcvarsall.bat file. + Expected versions are of the form {9, 10, 12, 14} + """ + vstools = "VS{0}0COMNTOOLS".format(version) + if vstools in os.environ: + return os.path.join(os.environ[vstools], '..\\..\\VC\\vcvarsall.bat') + else: + # prefer looking at env var; fall back to program files defaults + return os.path.join(PROGRAM_FILES_PATH, + 'Microsoft Visual Studio {}'.format(version), 'VC', + 'vcvarsall.bat') + + def msvc_env_cmd(bits, override=None): arch_selector = 'x86' if bits == 32 else 'amd64' @@ -196,11 +218,10 @@ def build(m, bld_bat, dirty=False, activate=True): fo.write(msvc_env_cmd(bits=cc.bits, override=m.get_value('build/msvc_compiler', None))) if activate: fo.write("call activate _build\n") - fo.write('\n') fo.write("REM ===== end generated header =====\n") fo.write(data) - cmd = [os.environ['COMSPEC'], '/c', 'call', 'bld.bat'] + cmd = [os.environ['COMSPEC'], '/c', 'bld.bat'] _check_call(cmd, cwd=src_dir) kill_processes() fix_staged_scripts() diff --git a/tests/test-recipes/metadata/_conda-build-test-environment-vars-in-build-env/bld.bat b/tests/test-recipes/metadata/_conda-build-test-environment-vars-in-build-env/bld.bat index 1a2f8ad626..cc6eed0c09 100644 --- a/tests/test-recipes/metadata/_conda-build-test-environment-vars-in-build-env/bld.bat +++ b/tests/test-recipes/metadata/_conda-build-test-environment-vars-in-build-env/bld.bat @@ -1,5 +1,8 @@ mkdir %PREFIX%\etc\conda\activate.d +:: output something so it's more obvious when scripts are running +echo "echo setting TEST_VAR" > %PREFIX%\etc\conda\activate.d\test.bat echo set TEST_VAR=1 > %PREFIX%\etc\conda\activate.d\test.bat mkdir %PREFIX%\etc\conda\deactivate.d +echo "echo setting TEST_VAR" > %PREFIX%\etc\conda\deactivate.d\test.bat echo set TEST_VAR= > %PREFIX%\etc\conda\deactivate.d\test.bat diff --git a/tests/test-recipes/metadata/_dirty_skip_section/bld.bat b/tests/test-recipes/metadata/_dirty_skip_section/bld.bat index 2100201c67..c870f4bf18 100644 --- a/tests/test-recipes/metadata/_dirty_skip_section/bld.bat +++ b/tests/test-recipes/metadata/_dirty_skip_section/bld.bat @@ -1,3 +1,4 @@ :: ensure that the DIRTY environment variable is available for logic in build scripts +echo DIRTY environment variable should be "1". Is currently: "%DIRTY%" IF "%DIRTY%" == "1" exit 0 exit 1 \ No newline at end of file diff --git a/tests/test-recipes/metadata/has_prefix_files/run_test.py b/tests/test-recipes/metadata/has_prefix_files/run_test.py index fb50fba2a0..3dbda3d572 100644 --- a/tests/test-recipes/metadata/has_prefix_files/run_test.py +++ b/tests/test-recipes/metadata/has_prefix_files/run_test.py @@ -20,13 +20,6 @@ def main(): print(data) assert prefix in data - with open(join(prefix, 'binary-has-prefix'), 'rb') as f: - data = f.read() - - print('binary-has-prefix') - print(data) - assert prefix.encode('utf-8') in data - if sys.platform == 'win32': forward_slash_prefix = prefix.replace('\\', '/') with open(join(prefix, 'forward-slash-prefix')) as f: @@ -35,6 +28,12 @@ def main(): print('forward-slash-prefix') print(data) assert forward_slash_prefix in data + else: + with open(join(prefix, 'binary-has-prefix'), 'rb') as f: + data = f.read() + print('binary-has-prefix') + print(data) + assert prefix.encode('utf-8') in data if __name__ == '__main__': main() diff --git a/tests/test-recipes/metadata/set_env_var_activate_build/bld.bat b/tests/test-recipes/metadata/set_env_var_activate_build/bld.bat index 358ee87d83..8f6830ed69 100644 --- a/tests/test-recipes/metadata/set_env_var_activate_build/bld.bat +++ b/tests/test-recipes/metadata/set_env_var_activate_build/bld.bat @@ -1 +1,2 @@ +echo TEST_VAR is "%TEST_VAR%" (should be "1") if "%TEST_VAR%" == "" exit 1 \ No newline at end of file