Files
platformio-core/platformio/project/helpers.py
2019-09-23 23:13:48 +03:00

235 lines
6.6 KiB
Python

# Copyright (c) 2014-present PlatformIO <contact@platformio.org>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import json
import os
from hashlib import sha1
from os import walk
from os.path import (
basename,
dirname,
expanduser,
isdir,
isfile,
join,
realpath,
splitdrive,
)
from click.testing import CliRunner
from platformio import __version__, exception
from platformio.compat import WINDOWS, hashlib_encode_data
from platformio.project.config import ProjectConfig
def get_project_dir():
return os.getcwd()
def is_platformio_project(project_dir=None):
if not project_dir:
project_dir = get_project_dir()
return isfile(join(project_dir, "platformio.ini"))
def find_project_dir_above(path):
if isfile(path):
path = dirname(path)
if is_platformio_project(path):
return path
if isdir(dirname(path)):
return find_project_dir_above(dirname(path))
return None
def get_project_optional_dir(name, default=None):
project_dir = get_project_dir()
config = ProjectConfig.get_instance(join(project_dir, "platformio.ini"))
optional_dir = config.get("platformio", name)
if not optional_dir:
return default
if "$PROJECT_HASH" in optional_dir:
optional_dir = optional_dir.replace(
"$PROJECT_HASH",
"%s-%s"
% (
basename(project_dir),
sha1(hashlib_encode_data(project_dir)).hexdigest()[:10],
),
)
if optional_dir.startswith("~"):
optional_dir = expanduser(optional_dir)
return realpath(optional_dir)
def get_project_core_dir():
default = join(expanduser("~"), ".platformio")
core_dir = get_project_optional_dir(
"core_dir", get_project_optional_dir("home_dir", default)
)
win_core_dir = None
if WINDOWS and core_dir == default:
win_core_dir = splitdrive(core_dir)[0] + "\\.platformio"
if isdir(win_core_dir):
core_dir = win_core_dir
if not isdir(core_dir):
try:
os.makedirs(core_dir)
except OSError as e:
if win_core_dir:
os.makedirs(win_core_dir)
core_dir = win_core_dir
else:
raise e
assert isdir(core_dir)
return core_dir
def get_project_global_lib_dir():
return get_project_optional_dir(
"globallib_dir", join(get_project_core_dir(), "lib")
)
def get_project_platforms_dir():
return get_project_optional_dir(
"platforms_dir", join(get_project_core_dir(), "platforms")
)
def get_project_packages_dir():
return get_project_optional_dir(
"packages_dir", join(get_project_core_dir(), "packages")
)
def get_project_cache_dir():
return get_project_optional_dir("cache_dir", join(get_project_core_dir(), ".cache"))
def get_project_workspace_dir():
return get_project_optional_dir("workspace_dir", join(get_project_dir(), ".pio"))
def get_project_build_dir(force=False):
path = get_project_optional_dir(
"build_dir", join(get_project_workspace_dir(), "build")
)
try:
if not isdir(path):
os.makedirs(path)
except Exception as e: # pylint: disable=broad-except
if not force:
raise Exception(e)
return path
def get_project_libdeps_dir():
return get_project_optional_dir(
"libdeps_dir", join(get_project_workspace_dir(), "libdeps")
)
def get_project_lib_dir():
return get_project_optional_dir("lib_dir", join(get_project_dir(), "lib"))
def get_project_include_dir():
return get_project_optional_dir("include_dir", join(get_project_dir(), "include"))
def get_project_src_dir():
return get_project_optional_dir("src_dir", join(get_project_dir(), "src"))
def get_project_test_dir():
return get_project_optional_dir("test_dir", join(get_project_dir(), "test"))
def get_project_boards_dir():
return get_project_optional_dir("boards_dir", join(get_project_dir(), "boards"))
def get_project_data_dir():
return get_project_optional_dir("data_dir", join(get_project_dir(), "data"))
def get_project_shared_dir():
return get_project_optional_dir("shared_dir", join(get_project_dir(), "shared"))
def compute_project_checksum(config):
# rebuild when PIO Core version changes
checksum = sha1(hashlib_encode_data(__version__))
# configuration file state
checksum.update(hashlib_encode_data(config.to_json()))
# project file structure
check_suffixes = (".c", ".cc", ".cpp", ".h", ".hpp", ".s", ".S")
for d in (get_project_include_dir(), get_project_src_dir(), get_project_lib_dir()):
if not isdir(d):
continue
chunks = []
for root, _, files in walk(d):
for f in files:
path = join(root, f)
if path.endswith(check_suffixes):
chunks.append(path)
if not chunks:
continue
chunks_to_str = ",".join(sorted(chunks))
if WINDOWS: # case insensitive OS
chunks_to_str = chunks_to_str.lower()
checksum.update(hashlib_encode_data(chunks_to_str))
return checksum.hexdigest()
def load_project_ide_data(project_dir, env_or_envs):
from platformio.commands.run import cli as cmd_run
assert env_or_envs
envs = env_or_envs
if not isinstance(envs, list):
envs = [envs]
args = ["--project-dir", project_dir, "--target", "idedata"]
for env in envs:
args.extend(["-e", env])
result = CliRunner().invoke(cmd_run, args)
if result.exit_code != 0 and not isinstance(
result.exception, exception.ReturnErrorCode
):
raise result.exception
if '"includes":' not in result.output:
raise exception.PlatformioException(result.output)
data = {}
for line in result.output.split("\n"):
line = line.strip()
if line.startswith('{"') and line.endswith("}") and "env_name" in line:
_data = json.loads(line)
if "env_name" in _data:
data[_data["env_name"]] = _data
if not isinstance(env_or_envs, list) and env_or_envs in data:
return data[env_or_envs]
return data or None