@@ -244,6 +244,14 @@ function build_sketch { # build_sketch <ide_path> <user_path> <path-to-ino> [ext
244244 fi
245245 fi
246246
247+ # Install libraries from ci.json if they exist
248+ install_libs -ai " $ide_path " -s " $sketchdir "
249+ install_result=$?
250+ if [ $install_result -ne 0 ]; then
251+ echo " ERROR: Library installation failed for $sketchname " >&2
252+ exit $install_result
253+ fi
254+
247255 ARDUINO_CACHE_DIR=" $HOME /.arduino/cache.tmp"
248256 if [ -n " $ARDUINO_BUILD_DIR " ]; then
249257 build_dir=" $ARDUINO_BUILD_DIR "
@@ -580,13 +588,168 @@ function build_sketches { # build_sketches <ide_path> <user_path> <target> <path
580588 return 0
581589}
582590
591+ # Return 0 if the string looks like a git URL we should pass to --git-url
592+ is_git_like_url () {
593+ local u=$1
594+ [[ " $u " =~ ^https? ://.+ ]] || [[ " $u " =~ ^git@[^:]+:.+ ]]
595+ }
596+
597+ # If status!=0, print errors/warnings from captured output (fallback to full output)
598+ print_err_warnings () {
599+ local status=$1 ; shift
600+ local out=$*
601+ if [ " $status " -ne 0 ]; then
602+ printf ' %s\n' " $out " | grep -Ei " error|warning|warn" >&2 || printf ' %s\n' " $out " >&2
603+ fi
604+ }
605+
606+ function install_libs { # install_libs <ide_path> <sketchdir> [-v]
607+ local ide_path=" "
608+ local sketchdir=" "
609+ local verbose=false
610+
611+ while [ -n " $1 " ]; do
612+ case " $1 " in
613+ -ai ) shift ; ide_path=$1 ;;
614+ -s ) shift ; sketchdir=$1 ;;
615+ -v ) verbose=true ;;
616+ * )
617+ echo " ERROR: Unknown argument: $1 " >&2
618+ echo " USAGE: install_libs -ai <ide_path> -s <sketchdir> [-v]" >&2
619+ return 1
620+ ;;
621+ esac
622+ shift
623+ done
624+
625+ if [ -z " $ide_path " ]; then
626+ echo " ERROR: IDE path not provided" >&2
627+ echo " USAGE: install_libs -ai <ide_path> -s <sketchdir> [-v]" >&2
628+ return 1
629+ fi
630+ if [ -z " $sketchdir " ]; then
631+ echo " ERROR: Sketch directory not provided" >&2
632+ echo " USAGE: install_libs -ai <ide_path> -s <sketchdir> [-v]" >&2
633+ return 1
634+ fi
635+ if [ ! -f " $ide_path /arduino-cli" ]; then
636+ echo " ERROR: arduino-cli not found at $ide_path /arduino-cli" >&2
637+ return 1
638+ fi
639+
640+ if [ ! -f " $sketchdir /ci.json" ]; then
641+ [ " $verbose " = true ] && echo " No ci.json found in $sketchdir , skipping library installation"
642+ return 0
643+ fi
644+ if ! jq -e . " $sketchdir /ci.json" > /dev/null 2>&1 ; then
645+ echo " ERROR: $sketchdir /ci.json is not valid JSON" >&2
646+ return 1
647+ fi
648+
649+ local libs_type
650+ libs_type=$( jq -r ' .libs | type' " $sketchdir /ci.json" 2> /dev/null)
651+ if [ -z " $libs_type " ] || [ " $libs_type " = " null" ]; then
652+ [ " $verbose " = true ] && echo " No libs field found in ci.json, skipping library installation"
653+ return 0
654+ elif [ " $libs_type " != " array" ]; then
655+ echo " ERROR: libs field in ci.json must be an array, found: $libs_type " >&2
656+ return 1
657+ fi
658+
659+ local libs_count
660+ libs_count=$( jq -r ' .libs | length' " $sketchdir /ci.json" 2> /dev/null)
661+ if [ " $libs_count " -eq 0 ]; then
662+ [ " $verbose " = true ] && echo " libs array is empty in ci.json, skipping library installation"
663+ return 0
664+ fi
665+
666+ echo " Installing $libs_count libraries from $sketchdir /ci.json"
667+
668+ local needs_unsafe=false
669+ local original_unsafe_setting=" "
670+ local libs
671+ libs=$( jq -r ' .libs[]? // empty' " $sketchdir /ci.json" )
672+
673+ # Detect any git-like URL (GitHub/GitLab/Bitbucket/self-hosted/ssh)
674+ for lib in $libs ; do
675+ if is_git_like_url " $lib " ; then
676+ needs_unsafe=true
677+ break
678+ fi
679+ done
680+
681+ if [ " $needs_unsafe " = true ]; then
682+ [ " $verbose " = true ] && echo " Checking current unsafe install setting..."
683+ original_unsafe_setting=$( " $ide_path /arduino-cli" config get library.enable_unsafe_install 2> /dev/null || echo " false" )
684+ if [ " $original_unsafe_setting " = " false" ]; then
685+ [ " $verbose " = true ] && echo " Enabling unsafe installs for Git URLs..."
686+ " $ide_path /arduino-cli" config set library.enable_unsafe_install true > /dev/null 2>&1 || \
687+ echo " WARNING: Failed to enable unsafe installs, Git URL installs may fail" >&2
688+ else
689+ [ " $verbose " = true ] && echo " Unsafe installs already enabled"
690+ fi
691+ fi
692+
693+ local rc=0 install_status=0 output=" "
694+ for lib in $libs ; do
695+ [ " $verbose " = true ] && echo " Processing library: $lib "
696+
697+ if is_git_like_url " $lib " ; then
698+ [ " $verbose " = true ] && echo " Installing library from git URL: $lib "
699+ if [ " $verbose " = true ]; then
700+ " $ide_path /arduino-cli" lib install --git-url " $lib "
701+ install_status=$?
702+ else
703+ output=$( " $ide_path /arduino-cli" lib install --git-url " $lib " 2>&1 )
704+ install_status=$?
705+ fi
706+ else
707+ [ " $verbose " = true ] && echo " Installing library by name: $lib "
708+ if [ " $verbose " = true ]; then
709+ " $ide_path /arduino-cli" lib install " $lib "
710+ install_status=$?
711+ else
712+ output=$( " $ide_path /arduino-cli" lib install " $lib " 2>&1 )
713+ install_status=$?
714+ fi
715+ fi
716+
717+ # Treat "already installed"/"up to date" as success (idempotent)
718+ if [ $install_status -ne 0 ] && echo " $output " | grep -qiE ' already installed|up to date' ; then
719+ install_status=0
720+ fi
721+
722+ if [ " $verbose " != true ]; then
723+ print_err_warnings " $install_status " " $output "
724+ fi
725+
726+ if [ $install_status -ne 0 ]; then
727+ echo " ERROR: Failed to install library: $lib " >&2
728+ rc=$install_status
729+ break
730+ else
731+ [ " $verbose " = true ] && echo " Successfully installed library: $lib "
732+ fi
733+ done
734+
735+ if [ " $needs_unsafe " = true ] && [ " $original_unsafe_setting " = " false" ]; then
736+ [ " $verbose " = true ] && echo " Restoring original unsafe install setting..."
737+ " $ide_path /arduino-cli" config set library.enable_unsafe_install false > /dev/null 2>&1 || true
738+ fi
739+
740+ [ $rc -eq 0 ] && echo " Library installation completed"
741+ return $rc
742+ }
743+
744+
583745USAGE="
584746USAGE: ${0} [command] [options]
585747Available commands:
586748 count: Count sketches.
587749 build: Build a sketch.
588750 chunk_build: Build a chunk of sketches.
589751 check_requirements: Check if target meets sketch requirements.
752+ install_libs: Install libraries from ci.json file.
590753"
591754
592755cmd=$1
@@ -606,6 +769,8 @@ case "$cmd" in
606769 ;;
607770 " check_requirements" ) check_requirements " $@ "
608771 ;;
772+ " install_libs" ) install_libs " $@ "
773+ ;;
609774 * )
610775 echo " ERROR: Unrecognized command"
611776 echo " $USAGE "
0 commit comments