def detect_windows_subsystem_test(self): # Dont raise test result = OSInfo.detect_windows_subsystem() if not OSInfo.bash_path() or platform.system() != "Windows": self.assertEqual(None, result) else: self.assertEqual(str, type(result))
def conditional_parameter_expansion_test(self): # https://github.com/conan-io/conan/issues/3911 client = TestClient() client.save({"conanfile.txt": ""}) client.run("profile new default --detect") client.run("profile update env.PREPEND_VAR=[1,2,three] default") client.run("install . -g virtualenv") activate = load(os.path.join(client.current_folder, "activate.sh")) self.assertIn( "PREPEND_VAR=\"1\":\"2\":\"three\"${PREPEND_VAR+:$PREPEND_VAR}", activate) client.runner("%s -c 'source \"%s/activate.sh\" && env'" % (OSInfo.bash_path(), client.current_folder)) # Check no trailing path separator ":" self.assertNotIn("PREPEND_VAR=1:2:three:", client.out) self.assertIn("PREPEND_VAR=1:2:three", client.out) # Check correct value # Check old value is preserved client.runner( "%s -c 'export PREPEND_VAR=kk && source \"%s/activate.sh\" && env'" % (OSInfo.bash_path(), client.current_folder)) self.assertIn("PREPEND_VAR=1:2:three:kk", client.out)
def run_in_windows_bash(conanfile, bashcmd, cwd=None, subsystem=None, msys_mingw=True, env=None): """ Will run a unix command inside a bash terminal It requires to have MSYS2, CYGWIN, or WSL """ env = env or {} if platform.system() != "Windows": raise ConanException("Command only for Windows operating system") subsystem = subsystem or OSInfo.detect_windows_subsystem() if not subsystem: raise ConanException( "Cannot recognize the Windows subsystem, install MSYS2/cygwin " "or specify a build_require to apply it.") if subsystem == MSYS2 and msys_mingw: # This needs to be set so that msys2 bash profile will set up the environment correctly. env_vars = { "MSYSTEM": ("MINGW32" if conanfile.settings.get_safe("arch") == "x86" else "MINGW64"), "MSYS2_PATH_TYPE": "inherit" } else: env_vars = {} with environment_append(env_vars): hack_env = "" # In the bash.exe from WSL this trick do not work, always the /usr/bin etc at first place if subsystem != WSL: def get_path_value(container, subsystem_name): """Gets the path from the container dict and returns a string with the path for the subsystem_name""" _path_key = next( (name for name in container.keys() if "path" == name.lower()), None) if _path_key: _path_value = container.get(_path_key) if isinstance(_path_value, list): return ":".join([ unix_path(path, path_flavor=subsystem_name) for path in _path_value ]) else: return unix_path(_path_value, path_flavor=subsystem_name) # First get the PATH from the conanfile.env inherited_path = get_path_value(conanfile.env, subsystem) # Then get the PATH from the real env env_path = get_path_value(env, subsystem) # Both together full_env = ":".join(v for v in [env_path, inherited_path] if v) # Put the build_requires and requires path at the first place inside the shell hack_env = ' && PATH="%s:$PATH"' % full_env if full_env else "" for var_name, value in env.items(): if var_name == "PATH": continue hack_env += ' && %s=%s' % (var_name, value) # Needed to change to that dir inside the bash shell if cwd and not os.path.isabs(cwd): cwd = os.path.join(get_cwd(), cwd) curdir = unix_path(cwd or get_cwd(), path_flavor=subsystem) to_run = 'cd "%s"%s && %s ' % (curdir, hack_env, bashcmd) bash_path = OSInfo.bash_path() bash_path = '"%s"' % bash_path if " " in bash_path else bash_path wincmd = '%s --login -c %s' % (bash_path, escape_windows_cmd(to_run)) conanfile.output.info('run_in_windows_bash: %s' % wincmd) # If is there any other env var that we know it contains paths, convert it to unix_path used_special_vars = [ var for var in ["AR", "AS", "RANLIB", "LD", "STRIP", "CC", "CXX"] if var in conanfile.env.keys() ] normalized_env = { p: unix_path(conanfile.env[p], path_flavor=subsystem) for p in used_special_vars } # https://github.com/conan-io/conan/issues/2839 (subprocess=True) with environment_append(normalized_env): return conanfile._conan_runner(wincmd, output=conanfile.output, subprocess=True)