platformio-core icon indicating copy to clipboard operation
platformio-core copied to clipboard

Sharing dependencies across environments

Open robsonos opened this issue 3 years ago • 7 comments

What kind of issue is this?

  • [*] Feature Request.

Configuration

Operating system: Windows 11 Pro

PlatformIO Version (platformio --version): PlatformIO Core, version 6.1.4

Description of problem

Hi, I was wondering if it is possible to create a feature to allow sharing dependencies across environments. I have a project with several dependencies with the same version and they end up getting downloaded multiple times.

Steps to Reproduce

pio run

Actual Results

The above command will create:

.pio
'-libdeps
  '-env1
     `-ArduinoJson
  '-env2
     `-ArduinoJson

Expected Results

Something like:

.pio
'-libdeps
  '-env-shared
     `-ArduinoJson

If problems with PlatformIO Build System:

The content of platformio.ini:

[env]
platform = nordicnrf52
board = adafruit_feather_nrf52840
framework = arduino
lib_deps = 
    bblanchon/ArduinoJson@^6.19.4

[env:env1]

[env:env2]

Source file to reproduce issue:

#include <Arduino.h>

void setup() {
  // put your setup code here, to run once:
}

void loop() {
  // put your main code here, to run repeatedly:
}

Additional info

robsonos avatar Nov 02 '22 06:11 robsonos

with several dependencies with the same version and they end up getting downloaded multiple times.

PlatformIO does not download dependencies multiple times, it uses a cache for HTTP and binary requests. So, don't worry about this.


Regarding common dependencies. You can put them in the lib folder. Libraries located here are sharable between environments.

ivankravets avatar Nov 02 '22 11:11 ivankravets

Hi @ivankravets,

I see. However, PlatformIO doesn't seem to cache dependencies from git (private) repositories (I apologise for not mentioning that before), which makes sense but it drastically slows down continuous integration. I am aware of the lib folder alternative, but I still wanna treat the libraries as dependencies as they are versioned per release (but not per environment).

Would it be able to achieve dependency sharing across environments with Advanced Scripting?

robsonos avatar Nov 02 '22 13:11 robsonos

Yes, https://docs.platformio.org/en/latest/scripting/index.html is the right solution. Just use the PRE script and pre-install dependencies to the lib folder. Also, you can keep declarations in the config and re-use them, see example https://docs.platformio.org/en/latest/scripting/examples/platformio_ini_custom_options.html

Another idea is to use the LibraryPackageManager API directly but I don't know how you are good in Python. See part of the code https://github.com/platformio/platformio-core/blob/develop/platformio/package/commands/install.py#L220

ivankravets avatar Nov 03 '22 10:11 ivankravets

^ I believe something like this was previously mentioned after lib_extra_dirs stopped working with lib_deps in #4206, so in our (espurna) case the only real option now is to manually install everything through the API

  • https://github.com/xoseperez/espurna/blob/cc90554b0e7e1c2923d3f08fd2ce1edeaec393f1/code/scripts/pio_pre.py#L62-L103 (...with a small addition of migrating .pio/ $env libs...)
  • https://github.com/xoseperez/espurna/blob/cc90554b0e7e1c2923d3f08fd2ce1edeaec393f1/code/scripts/pio_pre.py#L139-L144 (there is still a lib_deps-like variable, but installation happens on our explicit request. old versions removal included)
  • https://github.com/xoseperez/espurna/blob/cc90554b0e7e1c2923d3f08fd2ce1edeaec393f1/code/platformio.ini#L139-L140

mcspr avatar Nov 03 '22 18:11 mcspr

Thanks, guys. I was considering using LibraryPackageManager though was not sure how to approach this in extra_scripts as my understanding is that extra_scripts run after the Library Manager. What you sent looks promising @mcspr.

robsonos avatar Nov 04 '22 00:11 robsonos

Hi guys. I ended up going with something like this:

platformio.ini:

[env]
...
extra_scripts = pre:pre_script.py
lib_extra_dirs = .pio/libdeps/shared/
shared_lib_dir = .pio/libdeps/shared/
shared_lib_deps =
  https://github.com/...
  https://github.com/...
  https://github.com/...

pre_script.py:

from SCons.Script import ARGUMENTS
import subprocess
from os import makedirs
from os.path import isdir
Import("env")


def install_shared_dependencies(env, verbose):
    # Get shared_lib_dir
    shared_lib_dir = env.GetProjectOption('shared_lib_dir')

    # Create shared_lib_dirif it does not exist
    if (not isdir(shared_lib_dir)):
        makedirs(shared_lib_dir)

    # Get lib_deps
    config = env.GetProjectConfig()
    raw_lib_deps = env.GetProjectOption('shared_lib_deps')
    lib_deps = config.parse_multi_values(raw_lib_deps)

    # Build dependency installation command
    cmd = [env.subst("$PYTHONEXE"), "-m", "platformio", "pkg", "install"]
    cmd.extend(["--storage-dir", shared_lib_dir])

    # Add verbose to command
    if int(verbose) < 1:
        cmd.append("-s")

    # Add dependencies to command
    for lib in lib_deps:
        cmd.append("-l")
        cmd.append(lib)

    # Run command
    subprocess.check_call(cmd)


# Get verbose level
VERBOSE = ARGUMENTS.get("PIOVERBOSE", 0)

# Intall dependencies listed in env shared_lib_deps to shared_lib_dir
install_shared_dependencies(env, VERBOSE)

I am happy for this issue to be closed but I still see value in having a feature in platformio to do this.

Cheers.

robsonos avatar Nov 07 '22 01:11 robsonos