diff --git a/mussels/mussels.py b/mussels/mussels.py index f22e4ce..4229d61 100644 --- a/mussels/mussels.py +++ b/mussels/mussels.py @@ -24,6 +24,7 @@ import json import logging import os +import platform import sys import time from typing import * @@ -33,6 +34,7 @@ import mussels.bookshelf from mussels.utils import read from mussels.utils.versions import ( + NVC, sort_cookbook_by_version, sort_all_recipes_by_version, get_item_version, @@ -73,15 +75,15 @@ def __init__( log_level: log level ("DEBUG", "INFO", "WARNING", "ERROR"). """ self.log_file = log_file - self.__init_logging(log_level) + self._init_logging(log_level) self.app_data_dir = data_dir - self.__load_config("config.json", self.config) - self.__load_config("cookbooks.json", self.cookbooks) - self.__load_recipes() + self._load_config("config.json", self.config) + self._load_config("cookbooks.json", self.cookbooks) + self._load_recipes() - def __init_logging(self, level="DEBUG"): + def _init_logging(self, level="DEBUG"): """ Initializes the logging parameters @@ -111,7 +113,7 @@ def __init_logging(self, level="DEBUG"): self.logger.addHandler(filehandler) - def __load_config(self, filename, config) -> bool: + def _load_config(self, filename, config) -> bool: """ Load the cache. """ @@ -127,7 +129,7 @@ def __load_config(self, filename, config) -> bool: return True - def __store_config(self, filename, config) -> bool: + def _store_config(self, filename, config) -> bool: """ Update the cache. """ @@ -149,7 +151,7 @@ def __store_config(self, filename, config) -> bool: return True - def __read_cookbook(self, cookbook: str, cookbook_path: str) -> bool: + def _read_cookbook(self, cookbook: str, cookbook_path: str) -> bool: """ Load the recipes and tools from a single cookbook. """ @@ -157,8 +159,8 @@ def __read_cookbook(self, cookbook: str, cookbook_path: str) -> bool: sorted_tools: defaultdict = defaultdict(list) # Load the recipes and collections - recipes = read.recipes(os.path.join(cookbook_path, "recipes")) - recipes.update(read.recipes(os.path.join(cookbook_path, "collections"))) + recipes = read.recipes(os.path.join(cookbook_path, "recipes", platform.system())) + recipes.update(read.recipes(os.path.join(cookbook_path, "collections", platform.system()))) sorted_recipes = sort_cookbook_by_version(recipes) self.cookbooks[cookbook]["recipes"] = sorted_recipes @@ -169,7 +171,7 @@ def __read_cookbook(self, cookbook: str, cookbook_path: str) -> bool: self.recipes[recipe][version][cookbook] = recipes[recipe][version] # Load the tools - tools = read.tools(os.path.join(cookbook_path, "tools")) + tools = read.tools(os.path.join(cookbook_path, "tools", platform.system())) sorted_tools = sort_cookbook_by_version(tools) self.cookbooks[cookbook]["tools"] = sorted_tools @@ -184,7 +186,7 @@ def __read_cookbook(self, cookbook: str, cookbook_path: str) -> bool: return True - def __read_bookshelf(self) -> bool: + def _read_bookshelf(self) -> bool: """ Load the recipes and tools from cookbooks in ~/.mussels/cookbooks """ @@ -195,23 +197,23 @@ def __read_bookshelf(self) -> bool: os.path.join(self.app_data_dir, "cookbooks"), cookbook ) if os.path.isdir(cookbook_path): - if not self.__read_cookbook(cookbook, cookbook_path): + if not self._read_cookbook(cookbook, cookbook_path): self.logger.warning( f"Failed to read any recipes or tools from cookbook: {cookbook}" ) - self.__store_config("cookbooks.json", self.cookbooks) + self._store_config("cookbooks.json", self.cookbooks) return True - def __read_local_recipes(self) -> bool: + def _read_local_recipes(self) -> bool: """ Load the recipes and tools from local "mussels" directory """ # Load recipes and tools from `cwd`/mussels directory, if any exist. local_recipes = os.path.join(os.getcwd(), "mussels") if os.path.isdir(local_recipes): - if not self.__read_cookbook("local", local_recipes): + if not self._read_cookbook("local", local_recipes): return False self.cookbooks["local"]["url"] = "" @@ -220,16 +222,16 @@ def __read_local_recipes(self) -> bool: return True - def __load_recipes(self) -> bool: + def _load_recipes(self) -> bool: """ Load the recipes and tools. """ # If the cache is empty, try reading from the local bookshelf. if len(self.recipes) == 0 or len(self.tools) == 0: - self.__read_bookshelf() + self._read_bookshelf() # Load recipes from the local mussels directory, if those exists. - if not self.__read_local_recipes(): + if not self._read_local_recipes(): self.logger.warning( f"Local `mussels` directory found, but failed to load any recipes or tools." ) @@ -249,7 +251,7 @@ def __load_recipes(self) -> bool: return True - def __build_recipe( + def _build_recipe( self, recipe: str, version: str, cookbook: str, toolchain: dict ) -> dict: """ @@ -308,13 +310,15 @@ def __build_recipe( return result try: - builder = self.recipes[recipe][version](toolchain, self.app_data_dir) + builder = self.recipes[recipe][version][cookbook]( + toolchain, self.app_data_dir + ) except KeyError: self.logger.error(f"FAILED to find recipe: {recipe}-{version}!") result["time elapsed"] = time.time() - start return result - if not builder.__build(): + if not builder._build(): self.logger.error(f"FAILURE: {recipe}-{version} build failed!\n") else: self.logger.info(f"Success: {recipe}-{version} build succeeded. :)\n") @@ -324,7 +328,7 @@ def __build_recipe( return result - def __get_recipe_version(self, recipe: str) -> dict: + def _get_recipe_version(self, recipe: str) -> NVC: """ Select recipe version based on version requirements. Eliminate recipe versions and sorted tools versions based on @@ -361,7 +365,7 @@ def __get_recipe_version(self, recipe: str) -> dict: ) return nvc - def __identify_build_recipes(self, recipe: str, chain: list) -> list: + def _identify_build_recipes(self, recipe: str, chain: list) -> list: """ Identify all recipes that must be built given a specific recipe. @@ -370,28 +374,30 @@ def __identify_build_recipes(self, recipe: str, chain: list) -> list: chain: (in,out) A dependency chain starting from the first recursive call used to identify circular dependencies. """ - nvc = self.__get_recipe_version(recipe) + recipe_nvc = self._get_recipe_version(recipe) - if (len(chain) > 0) and (nvc["name"] == chain[0]): + if (len(chain) > 0) and (recipe_nvc.name == chain[0]): raise ValueError(f"Circular dependencies found! {chain}") - chain.append(nvc["name"]) + chain.append(recipe_nvc.name) recipes = [] recipes.append(recipe) - dependencies = self.recipes[nvc["name"]][nvc["version"]][nvc["cookbook"]].dependencies + dependencies = self.recipes[recipe_nvc.name][recipe_nvc.version][ + recipe_nvc.cookbook + ].dependencies for dependency in dependencies: if ":" not in dependency: - # If the cookbook isn't explicitlyl specified for the dependency, + # If the cookbook isn't explicitly specified for the dependency, # select the recipe from the current cookbook. - dependency = f"{nvc['cookbook']}:{dependency}" + dependency = f"{recipe_nvc.cookbook}:{dependency}" - recipes += self.__identify_build_recipes(dependency, chain) + recipes += self._identify_build_recipes(dependency, chain) return recipes - def __get_build_batches(self, recipe: str) -> list: + def _get_build_batches(self, recipe: str) -> list: """ Get list of build batches that can be built concurrently. @@ -399,38 +405,37 @@ def __get_build_batches(self, recipe: str) -> list: recipe: A recipes string in the format [cookbook:]recipe[==version]. """ # Identify all recipes that must be built given list of desired builds. - all_recipes = set(self.__identify_build_recipes(recipe, [])) + all_recipes = set(self._identify_build_recipes(recipe, [])) # Build a map of recipes (name,version) tuples to sets of dependency (name,version,cookbook) tuples - name_to_deps = {} + nvc_to_deps = {} for recipe in all_recipes: - nvc = self.__get_recipe_version(recipe) - dependencies = self.recipes[nvc["name"]][nvc["version"]][nvc["cookbook"]].dependencies - name_to_deps[nvc["name"]] = set( - [ - self.__get_recipe_version(dependency)[0] - for dependency in dependencies - ] + recipe_nvc = self._get_recipe_version(recipe) + dependencies = self.recipes[recipe_nvc.name][recipe_nvc.version][ + recipe_nvc.cookbook + ].dependencies + nvc_to_deps[recipe_nvc] = set( + [self._get_recipe_version(dependency) for dependency in dependencies] ) batches = [] # While there are dependencies to solve... - while name_to_deps: + while nvc_to_deps: # Get all recipes with no dependencies - ready = {recipe for recipe, deps in name_to_deps.items() if not deps} + ready = {recipe for recipe, deps in nvc_to_deps.items() if not deps} # If there aren't any, we have a loop in the graph if not ready: msg = "Circular dependencies found!\n" - msg += json.dumps(name_to_deps, indent=4) + msg += json.dumps(nvc_to_deps, indent=4) raise ValueError(msg) # Remove them from the dependency graph for recipe in ready: - del name_to_deps[recipe] - for deps in name_to_deps.values(): + del nvc_to_deps[recipe] + for deps in nvc_to_deps.values(): deps.difference_update(ready) # Add the batch to the list @@ -487,7 +492,7 @@ def print_results(results: list): else: recipe_str = f"{cookbook}:{recipe}" - batches = self.__get_build_batches(recipe_str) + batches = self._get_build_batches(recipe_str) # # Validate toolchain @@ -496,77 +501,63 @@ def print_results(results: list): toolchain = {} preferred_tool_versions = set() for i, bundle in enumerate(batches): - for j, recipe in enumerate(bundle): - highest_recipe_version = self.sorted_recipes[recipe][0] - highest_recipe_version_cookbook = highest_recipe_version["cookbooks"][0] - recipe_class = self.recipes[recipe][highest_recipe_version["version"]][ - highest_recipe_version_cookbook + for j, recipe_nvc in enumerate(bundle): + recipe_class = self.recipes[recipe_nvc.name][recipe_nvc.version][ + recipe_nvc.cookbook ] for tool in recipe_class.required_tools: - nvc = get_item_version(tool, self.sorted_tools) - preferred_tool_versions.add( - ( - nvc["name"], - nvc["version"], - nvc["cookbook"], - ) - ) + tool_nvc = get_item_version(tool, self.sorted_tools) + preferred_tool_versions.add(tool_nvc) # Check if required tools are installed missing_tools = [] - for ( - preferred_tool_name, - preferred_tool_version, - preferred_tool_cookbook, - ) in preferred_tool_versions: + for tool_nvc in preferred_tool_versions: tool_found = False - prefered_tool = self.tools[preferred_tool_name][preferred_tool_version][ - preferred_tool_cookbook + prefered_tool = self.tools[tool_nvc.name][tool_nvc.version][ + tool_nvc.cookbook ](self.app_data_dir) if prefered_tool.detect(): # Preferred tool version is available. tool_found = True - toolchain[preferred_tool_name] = prefered_tool - self.logger.info( - f" {preferred_tool_name}-{preferred_tool_version} found." - ) + toolchain[tool_nvc.name] = prefered_tool + self.logger.info(f" {tool_nvc.name}-{tool_nvc.version} found.") else: # Check if non-prefered (older, but compatible) version is available. self.logger.warning( - f" {preferred_tool_name}-{preferred_tool_version} not found." + f" {tool_nvc.name}-{tool_nvc.version} not found." ) - if len(self.sorted_tools[preferred_tool_name]) > 1: + if len(self.sorted_tools[tool_nvc.name]) > 1: self.logger.warning(f" Checking for alternative versions...") - alternative_versions = self.sorted_tools[preferred_tool_name][1:] + alternative_versions = self.sorted_tools[tool_nvc.name][1:] for alternative_version in alternative_versions: - alternative_tool = self.tools[preferred_tool_name][ + alternative_tool = self.tools[tool_nvc.name][ alternative_version["version"] ][alternative_version["cookbooks"][0]](self.app_data_dir) if alternative_tool.detect(): # Found a compatible version to use. tool_found = True - toolchain[preferred_tool_name] = alternative_tool + toolchain[tool_nvc.name] = alternative_tool # Select the version so it will be the default. get_item_version( - f"{alternative_version['cookbooks'][0]}:{preferred_tool_name}={alternative_version['version']}", + f"{alternative_version['cookbooks'][0]}:{tool_nvc.name}={alternative_version['version']}", self.sorted_tools, ) self.logger.info( - f" Alternative version {preferred_tool_name}-{alternative_version} found." + f" Alternative version {tool_nvc.name}-{alternative_version} found." ) else: self.logger.warning( - f" Alternative version {preferred_tool_name}-{alternative_version} not found." + f" Alternative version {tool_nvc.name}-{alternative_version} not found." ) if not tool_found: # Tool is missing. Build will fail. - missing_tools.append(preferred_tool_version) + missing_tools.append(tool_nvc.version) if len(missing_tools) > 0: self.logger.warning("") @@ -597,30 +588,33 @@ def print_results(results: list): idx = 0 failure = False for i, bundle in enumerate(batches): - for j, recipe in enumerate(bundle): + for j, recipe_nvc in enumerate(bundle): idx += 1 if dry_run: self.logger.info( - f" {idx:2} [{i}:{j:2}]: {recipe}-{self.sorted_recipes[recipe][0]}" + f" {idx:2} [{i}:{j:2}]: {recipe_nvc.cookbook}:{recipe_nvc.name}-{recipe_nvc.version}" ) self.logger.debug(f" Tool(s):") - for tool in self.recipes[recipe][ - self.sorted_recipes[recipe][0]["version"] - ][self.sorted_recipes[recipe][0]["cookbooks"][0]].required_tools: - nvc = get_item_version(tool, self.sorted_tools) + for tool in self.recipes[recipe_nvc.name][recipe_nvc.version][ + recipe_nvc.cookbook + ].required_tools: + tool_nvc = get_item_version(tool, self.sorted_tools) self.logger.debug( - f" {nvc['cookbook']}:{nvc['name']}-{nvc['version']}" + f" {tool_nvc.cookbook}:{tool_nvc.name}-{tool_nvc.version}" ) continue if failure: self.logger.warning( - f"Skipping {recipe} build due to prior failure." + f"Skipping {recipe_nvc.cookbook}:{recipe_nvc.name}-{recipe_nvc.version} build due to prior failure." ) else: - result = self.__build_recipe( - recipe, self.sorted_recipes[recipe][0], cookbook, toolchain + result = self._build_recipe( + recipe_nvc.name, + recipe_nvc.version, + recipe_nvc.cookbook, + toolchain, ) results.append(result) if not result["success"]: @@ -784,9 +778,9 @@ def update_cookbooks(self) -> None: repo = git.Repo(repo_dir) repo.git.pull() - self.__read_cookbook(book, repo_dir) + self._read_cookbook(book, repo_dir) - self.__store_config("cookbooks.json", self.cookbooks) + self._store_config("cookbooks.json", self.cookbooks) def list_cookbooks(self, verbose: bool = False): """ @@ -867,7 +861,7 @@ def config_trust_cookbook(self, cookbook): self.cookbooks[cookbook]["trusted"] = True - self.__store_config("cookbooks.json", self.cookbooks) + self._store_config("cookbooks.json", self.cookbooks) def config_add_cookbook(self, cookbook, author, url): """ @@ -877,9 +871,9 @@ def config_add_cookbook(self, cookbook, author, url): self.cookbooks[cookbook]["url"] = url self.cookbooks[cookbook]["trusted"] = True - self.__store_config("cookbooks.json", self.cookbooks) + self._store_config("cookbooks.json", self.cookbooks) def config_remove_cookbook(self, cookbook): self.cookbooks.pop(cookbook) - self.__store_config("cookbooks.json", self.cookbooks) + self._store_config("cookbooks.json", self.cookbooks) diff --git a/mussels/recipe.py b/mussels/recipe.py index b5bac0e..cd22ed2 100644 --- a/mussels/recipe.py +++ b/mussels/recipe.py @@ -58,9 +58,9 @@ class BaseRecipe(object): # will change: # v2.3.4 to nghttp2-2.3.4. # This hack is necessary because archives with changed names will extract to their original directory name. - archive_name_change = ("", "") + archive_name_change: tuple = ("", "") - install_paths = { + install_paths: dict = { # "x86": { # "include" : [], # "Destination directory": ["list", "of", "source", "items"], # "lib" : [], # Will copy source item to destination directory, @@ -77,15 +77,15 @@ class BaseRecipe(object): # }, } - platform = [] + platform: list = [] # Dependencies on other Mussels builds. # str format: name@version. # "@version" is optional. # If version is omitted, the default (highest) will be selected. - dependencies = [] + dependencies: list = [] - required_tools = [] # List of tools required by the build commands. + required_tools: list = [] # List of tools required by the build commands. # build_script is a dictionary containing build scripts for each build target. # Variables in "".format() syntax will be evaluated at build time. @@ -96,7 +96,7 @@ class BaseRecipe(object): # - includes: The install/{build}/include directory. # - libs: The install/{build}/lib directory. # - build: The build directory for a given build. - build_script = { + build_script: dict = { # "x86": """ # """, # "x64": """ @@ -105,7 +105,7 @@ class BaseRecipe(object): # """, } - builds = {} # Dictionary of build paths. + builds: dict = {} # Dictionary of build paths. # The following will be defined during the build and exist here for convenience # when writing build_script's using the f-string `f` prefix to help remember the @@ -135,14 +135,14 @@ def __init__(self, toolchain: dict, data_dir: str = ""): self.srcdir = os.path.join(self.data_dir, "src") os.makedirs(self.srcdir, exist_ok=True) - self.__init_logging() + self._init_logging() self.toolchain = toolchain # Skip download & build steps for collections. if self.is_collection == False: # Download and build if necessary. - if self.__download_archive() == False: + if self._download_archive() == False: raise ( Exception( f"Failed to download source archive for {self.name}-{self.version}" @@ -150,7 +150,7 @@ def __init__(self, toolchain: dict, data_dir: str = ""): ) # Extract to the data_dir. - if self.__extract_archive() == False: + if self._extract_archive() == False: raise ( Exception( f"Failed to extract source archive for {self.name}-{self.version}" @@ -162,7 +162,7 @@ def __init__(self, toolchain: dict, data_dir: str = ""): os.path.split(os.path.abspath(module_file))[0], "patches" ) - def __init_logging(self): + def _init_logging(self): """ Initializes the logging parameters """ @@ -186,7 +186,7 @@ def __init_logging(self): self.logger.addHandler(filehandler) - def __download_archive(self) -> bool: + def _download_archive(self) -> bool: """ Use the URL to download the archive if it doesn't already exist in the Downloads directory. """ @@ -224,7 +224,7 @@ def __download_archive(self) -> bool: return True - def __extract_archive(self) -> bool: + def _extract_archive(self) -> bool: """ Extract the archive found in Downloads directory, if necessary. """ @@ -262,7 +262,7 @@ def __extract_archive(self) -> bool: return True - def __install(self, build): + def _install(self, build): """ Copy the headers and libs to an install directory. """ @@ -306,7 +306,7 @@ def __install(self, build): self.logger.info(f"{self.name}-{self.version} {build} install succeeded.") return True - def __build(self) -> bool: + def _build(self) -> bool: """ First, patch source materials if not already patched. Then, for each architecture, run the build commands if the output files don't already exist. @@ -317,7 +317,7 @@ def __build(self) -> bool: ) return True - if os.path.isdir(self.patches) == "": + if not os.path.isdir(self.patches): self.logger.debug(f"No patch directory found.") else: # Patches exists for this recipe. @@ -481,7 +481,7 @@ def __build(self) -> bool: self.logger.info(f"{self.name}-{self.version} {build} build succeeded.") os.chdir(cwd) - if self.__install(build) == False: + if self._install(build) == False: return False return True diff --git a/mussels/recipes/Windows/bzip2/1.0.6/bzip2__1_0_6.py b/mussels/recipes/Windows/bzip2/1.0.6/bzip2__1_0_6.py index 2cf0d91..da7a3c5 100644 --- a/mussels/recipes/Windows/bzip2/1.0.6/bzip2__1_0_6.py +++ b/mussels/recipes/Windows/bzip2/1.0.6/bzip2__1_0_6.py @@ -40,6 +40,7 @@ class Recipe(BaseRecipe): "lib": [os.path.join("libbz2.dll"), os.path.join("libbz2.lib")], }, } + platform = ["Windows"] dependencies = [] required_tools = ["visualstudio==2017"] build_script = { diff --git a/mussels/recipes/Windows/bzip2/1.0.7/bzip2__1_0_7.py b/mussels/recipes/Windows/bzip2/1.0.7/bzip2__1_0_7.py index ecfc502..a961449 100644 --- a/mussels/recipes/Windows/bzip2/1.0.7/bzip2__1_0_7.py +++ b/mussels/recipes/Windows/bzip2/1.0.7/bzip2__1_0_7.py @@ -40,6 +40,7 @@ class Recipe(BaseRecipe): "lib": [os.path.join("libbz2.dll"), os.path.join("libbz2.lib")], }, } + platform = ["Windows"] dependencies = [] required_tools = ["visualstudio==2017"] build_script = { diff --git a/mussels/recipes/Windows/bzip2/1.1.0/bzip2__1_1_0.py b/mussels/recipes/Windows/bzip2/1.1.0/bzip2__1_1_0.py index aec25d3..615506a 100644 --- a/mussels/recipes/Windows/bzip2/1.1.0/bzip2__1_1_0.py +++ b/mussels/recipes/Windows/bzip2/1.1.0/bzip2__1_1_0.py @@ -37,6 +37,7 @@ class Recipe(BaseRecipe): "lib": [os.path.join("libbz2.dll"), os.path.join("libbz2.lib")], }, } + platform = ["Windows"] dependencies = [] required_tools = ["cmake", "visualstudio==2017"] build_script = { diff --git a/mussels/recipes/Windows/clamav/0.101.2/clamav__0_101_2.py b/mussels/recipes/Windows/clamav/0.101.2/clamav__0_101_2.py index 13aca1d..ac96734 100644 --- a/mussels/recipes/Windows/clamav/0.101.2/clamav__0_101_2.py +++ b/mussels/recipes/Windows/clamav/0.101.2/clamav__0_101_2.py @@ -92,6 +92,7 @@ class Recipe(BaseRecipe): ], }, } + platform = ["Windows"] dependencies = ["openssl"] required_tools = ["visualstudio>=2015"] build_script = { diff --git a/mussels/recipes/Windows/clamav/0.102-dev/clamav__0_102_dev.py b/mussels/recipes/Windows/clamav/0.102-dev/clamav__0_102_dev.py index 3a3b0dc..7b8743e 100644 --- a/mussels/recipes/Windows/clamav/0.102-dev/clamav__0_102_dev.py +++ b/mussels/recipes/Windows/clamav/0.102-dev/clamav__0_102_dev.py @@ -95,6 +95,7 @@ class Recipe(BaseRecipe): ], }, } + platform = ["Windows"] dependencies = [ "curl", "json_c", diff --git a/mussels/recipes/Windows/curl/1.2.11/curl__1_2_11.py b/mussels/recipes/Windows/curl/1.2.11/curl__1_2_11.py index 8b02774..a07ec44 100644 --- a/mussels/recipes/Windows/curl/1.2.11/curl__1_2_11.py +++ b/mussels/recipes/Windows/curl/1.2.11/curl__1_2_11.py @@ -43,6 +43,7 @@ class Recipe(BaseRecipe): ], }, } + platform = ["Windows"] dependencies = ["openssl", "nghttp2>=1.0.0", "libssh2", "zlib"] required_tools = ["cmake", "visualstudio>=2017"] build_script = { diff --git a/mussels/recipes/Windows/json_c/0.13.1/json_c__0_13_1.py b/mussels/recipes/Windows/json_c/0.13.1/json_c__0_13_1.py index 10338ce..3556b84 100644 --- a/mussels/recipes/Windows/json_c/0.13.1/json_c__0_13_1.py +++ b/mussels/recipes/Windows/json_c/0.13.1/json_c__0_13_1.py @@ -75,6 +75,7 @@ class Recipe(BaseRecipe): ], }, } + platform = ["Windows"] dependencies = [] required_tools = ["cmake", "visualstudio>=2017"] build_script = { diff --git a/mussels/recipes/Windows/libssh2/1.8.1/libssh2__1_8_1.py b/mussels/recipes/Windows/libssh2/1.8.1/libssh2__1_8_1.py index 9b2d807..093e483 100644 --- a/mussels/recipes/Windows/libssh2/1.8.1/libssh2__1_8_1.py +++ b/mussels/recipes/Windows/libssh2/1.8.1/libssh2__1_8_1.py @@ -51,6 +51,7 @@ class Recipe(BaseRecipe): ], }, } + platform = ["Windows"] dependencies = ["openssl>=1.1.0", "zlib"] required_tools = ["cmake", "visualstudio>=2017"] build_script = { diff --git a/mussels/recipes/Windows/libxml2/2.9.9/libxml2__2_9_9.py b/mussels/recipes/Windows/libxml2/2.9.9/libxml2__2_9_9.py index e425068..8a69bea 100644 --- a/mussels/recipes/Windows/libxml2/2.9.9/libxml2__2_9_9.py +++ b/mussels/recipes/Windows/libxml2/2.9.9/libxml2__2_9_9.py @@ -44,6 +44,7 @@ class Recipe(BaseRecipe): ], }, } + platform = ["Windows"] dependencies = [] required_tools = ["visualstudio>=2017"] build_script = { diff --git a/mussels/recipes/Windows/nghttp2/1.36.0/nghttp2__1_36_0.py b/mussels/recipes/Windows/nghttp2/1.36.0/nghttp2__1_36_0.py index 2531ded..ee96510 100644 --- a/mussels/recipes/Windows/nghttp2/1.36.0/nghttp2__1_36_0.py +++ b/mussels/recipes/Windows/nghttp2/1.36.0/nghttp2__1_36_0.py @@ -44,6 +44,7 @@ class Recipe(BaseRecipe): ], }, } + platform = ["Windows"] dependencies = ["openssl>=1.0.1", "zlib>=1.2.3"] required_tools = ["cmake", "visualstudio>=2017"] build_script = { diff --git a/mussels/recipes/Windows/openssl/1.1.0j/openssl__1_1_0j.py b/mussels/recipes/Windows/openssl/1.1.0j/openssl__1_1_0j.py index db0ff31..c841325 100644 --- a/mussels/recipes/Windows/openssl/1.1.0j/openssl__1_1_0j.py +++ b/mussels/recipes/Windows/openssl/1.1.0j/openssl__1_1_0j.py @@ -47,6 +47,7 @@ class Recipe(BaseRecipe): ], }, } + platform = ["Windows"] dependencies = ["zlib"] required_tools = ["nasm", "perl", "visualstudio>=2017"] build_script = { diff --git a/mussels/recipes/Windows/openssl/1.1.1b/openssl__1_1_1b.py b/mussels/recipes/Windows/openssl/1.1.1b/openssl__1_1_1b.py index ab1a098..a4b6582 100644 --- a/mussels/recipes/Windows/openssl/1.1.1b/openssl__1_1_1b.py +++ b/mussels/recipes/Windows/openssl/1.1.1b/openssl__1_1_1b.py @@ -47,6 +47,7 @@ class Recipe(BaseRecipe): ], }, } + platform = ["Windows"] dependencies = ["zlib"] required_tools = ["nasm", "perl", "visualstudio>=2017"] build_script = { diff --git a/mussels/recipes/Windows/pcre2/10.33/pcre2__10_33.py b/mussels/recipes/Windows/pcre2/10.33/pcre2__10_33.py index 8a79a2c..852de6f 100644 --- a/mussels/recipes/Windows/pcre2/10.33/pcre2__10_33.py +++ b/mussels/recipes/Windows/pcre2/10.33/pcre2__10_33.py @@ -43,6 +43,7 @@ class Recipe(BaseRecipe): ], }, } + platform = ["Windows"] dependencies = ["bzip2", "zlib"] required_tools = ["cmake", "visualstudio>=2017"] build_script = { diff --git a/mussels/recipes/Windows/pthread_win32/1.11.0/pthreads__1_11_0.py b/mussels/recipes/Windows/pthread_win32/1.11.0/pthreads__1_11_0.py index e04622f..97c2952 100644 --- a/mussels/recipes/Windows/pthread_win32/1.11.0/pthreads__1_11_0.py +++ b/mussels/recipes/Windows/pthread_win32/1.11.0/pthreads__1_11_0.py @@ -38,6 +38,7 @@ class Recipe(BaseRecipe): "lib": ["pthreadVC1.dll", "pthreadVC1.lib"], }, } + platform = ["Windows"] dependencies = [] required_tools = ["visualstudio>=2017"] build_script = { diff --git a/mussels/recipes/Windows/pthread_win32/2.9.1/pthreads__2_9_1.py b/mussels/recipes/Windows/pthread_win32/2.9.1/pthreads__2_9_1.py index 906877c..c0750fe 100644 --- a/mussels/recipes/Windows/pthread_win32/2.9.1/pthreads__2_9_1.py +++ b/mussels/recipes/Windows/pthread_win32/2.9.1/pthreads__2_9_1.py @@ -38,6 +38,7 @@ class Recipe(BaseRecipe): "lib": ["pthreadVC2.dll", "pthreadVC2.lib"], }, } + platform = ["Windows"] dependencies = [] required_tools = ["visualstudio>=2017"] build_script = { diff --git a/mussels/recipes/Windows/zlib/1.2.11/zlib__1_2_11.py b/mussels/recipes/Windows/zlib/1.2.11/zlib__1_2_11.py index 7ffc825..c5c236e 100644 --- a/mussels/recipes/Windows/zlib/1.2.11/zlib__1_2_11.py +++ b/mussels/recipes/Windows/zlib/1.2.11/zlib__1_2_11.py @@ -43,6 +43,7 @@ class Recipe(BaseRecipe): ], }, } + platform = ["Windows"] dependencies = [] required_tools = ["cmake", "visualstudio>=2017"] build_script = { diff --git a/mussels/tool.py b/mussels/tool.py index 97fbda0..108eae5 100644 --- a/mussels/tool.py +++ b/mussels/tool.py @@ -78,9 +78,9 @@ def __init__(self, data_dir: str = ""): self.logs_dir = os.path.join(os.path.abspath(data_dir), "logs", "tools") os.makedirs(self.logs_dir, exist_ok=True) - self.__init_logging() + self._init_logging() - def __init_logging(self): + def _init_logging(self): """ Initializes the logging parameters """ diff --git a/mussels/tools/Darwin/clang/clang.py b/mussels/tools/Darwin/clang/clang.py index 5a47192..bd8007b 100644 --- a/mussels/tools/Darwin/clang/clang.py +++ b/mussels/tools/Darwin/clang/clang.py @@ -28,6 +28,7 @@ class Tool(BaseTool): name = "clang" version = "10" url = "" + platform = ["Darwin"] path_mods = { "usr": {"host": []}, diff --git a/mussels/tools/Darwin/cmake/cmake__3_14.py b/mussels/tools/Darwin/cmake/cmake__3_14.py index 8deb203..f8dc578 100644 --- a/mussels/tools/Darwin/cmake/cmake__3_14.py +++ b/mussels/tools/Darwin/cmake/cmake__3_14.py @@ -28,6 +28,7 @@ class Tool(BaseTool): name = "cmake" version = "3.14" url = "" + platform = ["Darwin"] path_mods = { "usr": {"host": []}, diff --git a/mussels/tools/Darwin/make/make.py b/mussels/tools/Darwin/make/make.py index a58036f..de9e02d 100644 --- a/mussels/tools/Darwin/make/make.py +++ b/mussels/tools/Darwin/make/make.py @@ -28,6 +28,7 @@ class Tool(BaseTool): name = "make" version = "3" url = "" + platform = ["Darwin"] path_mods = { "usr": {"host": []}, diff --git a/mussels/tools/Darwin/meson/meson__0_51.py b/mussels/tools/Darwin/meson/meson__0_51.py index 32c9629..abcac50 100644 --- a/mussels/tools/Darwin/meson/meson__0_51.py +++ b/mussels/tools/Darwin/meson/meson__0_51.py @@ -28,6 +28,7 @@ class Tool(BaseTool): name = "meson" version = "0.51.0" url = "" + platform = ["Darwin"] path_mods = { "system": {"host": []}, diff --git a/mussels/tools/Windows/cmake/cmake__3_14_1.py b/mussels/tools/Windows/cmake/cmake__3_14_1.py index 42286cb..19a6218 100644 --- a/mussels/tools/Windows/cmake/cmake__3_14_1.py +++ b/mussels/tools/Windows/cmake/cmake__3_14_1.py @@ -27,6 +27,7 @@ class Tool(BaseTool): name = "cmake" version = "3.14.1" url = "https://github.com/Kitware/CMake/releases/download/v3.14.1/cmake-3.14.1-win64-x64.zip" + platform = ["Windows"] path_mods = { "system": { diff --git a/mussels/tools/Windows/nasm/nasm__2_14_02.py b/mussels/tools/Windows/nasm/nasm__2_14_02.py index ae67295..74f6ba1 100644 --- a/mussels/tools/Windows/nasm/nasm__2_14_02.py +++ b/mussels/tools/Windows/nasm/nasm__2_14_02.py @@ -27,6 +27,7 @@ class Tool(BaseTool): name = "nasm" version = "2.14.02" url = "https://www.nasm.us/pub/nasm/releasebuilds/2.14.02/win64/nasm-2.14.02-win64.zip" + platform = ["Windows"] path_mods = { "system": { diff --git a/mussels/tools/Windows/perl/perl__5_26_3_2603.py b/mussels/tools/Windows/perl/perl__5_26_3_2603.py index 6756ac7..fff6ad6 100644 --- a/mussels/tools/Windows/perl/perl__5_26_3_2603.py +++ b/mussels/tools/Windows/perl/perl__5_26_3_2603.py @@ -27,6 +27,7 @@ class Tool(BaseTool): name = "perl" version = "5.26.3.2603" url = "https://downloads.activestate.com/ActivePerl/releases/5.26.3.2603/ActivePerl-5.26.3.2603-MSWin32-x64-a95bce075.exe" + platform = ["Windows"] path_mods = { "system": { diff --git a/mussels/tools/Windows/visualstudio/visualstudio__2015.py b/mussels/tools/Windows/visualstudio/visualstudio__2015.py index e77b4c6..6ce51e3 100644 --- a/mussels/tools/Windows/visualstudio/visualstudio__2015.py +++ b/mussels/tools/Windows/visualstudio/visualstudio__2015.py @@ -27,6 +27,7 @@ class Tool(BaseTool): name = "visualstudio" version = "2015" url = "" + platform = ["Windows"] path_mods = { "system": { diff --git a/mussels/tools/Windows/visualstudio/visualstudio__2017.py b/mussels/tools/Windows/visualstudio/visualstudio__2017.py index a2f38f6..b66b642 100644 --- a/mussels/tools/Windows/visualstudio/visualstudio__2017.py +++ b/mussels/tools/Windows/visualstudio/visualstudio__2017.py @@ -27,6 +27,7 @@ class Tool(BaseTool): name = "visualstudio" version = "2017" url = "https://download.visualstudio.microsoft.com/download/pr/cb4bb895-e020-49e0-8cb0-1cdeeb1bfc2f/0224f1b33e9624fd445c582b375c4076/vs_community.exe" + platform = ["Windows"] path_mods = { "system": { diff --git a/mussels/tools/Windows/visualstudio/visualstudio__2019.py b/mussels/tools/Windows/visualstudio/visualstudio__2019.py index a72b941..a2c7ded 100644 --- a/mussels/tools/Windows/visualstudio/visualstudio__2019.py +++ b/mussels/tools/Windows/visualstudio/visualstudio__2019.py @@ -27,6 +27,7 @@ class Tool(BaseTool): name = "visualstudio" version = "2019" url = "https://github.com/Kitware/CMake/releases/download/v3.14.1/cmake-3.14.1-win64-x64.zip" + platform = ["Windows"] path_mods = { "system": { diff --git a/mussels/utils/read.py b/mussels/utils/read.py index b1ae12e..1076e9f 100644 --- a/mussels/utils/read.py +++ b/mussels/utils/read.py @@ -27,6 +27,7 @@ def recipes(recipe_path): Collect all Recipes in a directory. """ recipes = defaultdict(dict) + platform_ = platform.system() if not os.path.exists(recipe_path): return recipes @@ -37,9 +38,8 @@ def recipes(recipe_path): [os.path.join(root, directory)] ): _module = loader.find_module(module_name).load_module(module_name) - globals()[module_name] = _module if "Recipe" in dir(_module): - if platform.system() in _module.Recipe.platform: + if platform_ in _module.Recipe.platform: recipes[_module.Recipe.name][ _module.Recipe.version ] = _module.Recipe @@ -52,6 +52,7 @@ def tools(tool_path): Collect all Tools in a directory. """ tools = defaultdict(dict) + platform_ = platform.system() if not os.path.exists(tool_path): return tools @@ -62,8 +63,8 @@ def tools(tool_path): [os.path.join(root, directory)] ): _module = loader.find_module(module_name).load_module(module_name) - globals()[module_name] = _module if "Tool" in dir(_module): - tools[_module.Tool.name][_module.Tool.version] = _module.Tool + if platform_ in _module.Tool.platform: + tools[_module.Tool.name][_module.Tool.version] = _module.Tool return tools diff --git a/mussels/utils/versions.py b/mussels/utils/versions.py index 16e9463..4133e5a 100644 --- a/mussels/utils/versions.py +++ b/mussels/utils/versions.py @@ -16,7 +16,9 @@ limitations under the License. """ -from collections import defaultdict +from collections import defaultdict, namedtuple + +NVC = namedtuple("NVC", "name version cookbook") def version_keys(s): @@ -40,7 +42,7 @@ def sort_cookbook_by_version(items) -> defaultdict: """ Sort items, and determine the highest versions. """ - sorted_items = defaultdict(list) + sorted_items: defaultdict = defaultdict(list) for item in items: versions_list = list(items[item].keys()) @@ -56,7 +58,7 @@ def sort_all_recipes_by_version(items) -> defaultdict: """ Sort items, and determine the highest versions. """ - sorted_items = defaultdict(list) + sorted_items: defaultdict = defaultdict(list) for item in items: versions_list = list(items[item].keys()) @@ -93,7 +95,7 @@ def compare_versions(version_a: str, version_b: str) -> int: return 1 -def get_item_version(item_name: str, sorted_items: dict) -> dict: +def get_item_version(item_name: str, sorted_items: dict) -> NVC: """ Convert a item name in the below format to a (name, version) tuple: @@ -327,4 +329,4 @@ def get_item_version(item_name: str, sorted_items: dict) -> dict: f"No versions available to satisfy requirement for {requested_item}" ) - return nvc + return NVC(nvc["name"], nvc["version"], nvc["cookbook"])