mirror of
https://github.com/platformio/platformio-core.git
synced 2025-10-05 01:50:56 +02:00
235 lines
6.6 KiB
Python
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
|