@@ -244,6 +244,14 @@ function build_sketch { # build_sketch <ide_path> <user_path> <path-to-ino> [ext
244
244
fi
245
245
fi
246
246
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
+
247
255
ARDUINO_CACHE_DIR=" $HOME /.arduino/cache.tmp"
248
256
if [ -n " $ARDUINO_BUILD_DIR " ]; then
249
257
build_dir=" $ARDUINO_BUILD_DIR "
@@ -580,13 +588,168 @@ function build_sketches { # build_sketches <ide_path> <user_path> <target> <path
580
588
return 0
581
589
}
582
590
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
+
583
745
USAGE="
584
746
USAGE: ${0} [command] [options]
585
747
Available commands:
586
748
count: Count sketches.
587
749
build: Build a sketch.
588
750
chunk_build: Build a chunk of sketches.
589
751
check_requirements: Check if target meets sketch requirements.
752
+ install_libs: Install libraries from ci.json file.
590
753
"
591
754
592
755
cmd=$1
@@ -606,6 +769,8 @@ case "$cmd" in
606
769
;;
607
770
" check_requirements" ) check_requirements " $@ "
608
771
;;
772
+ " install_libs" ) install_libs " $@ "
773
+ ;;
609
774
* )
610
775
echo " ERROR: Unrecognized command"
611
776
echo " $USAGE "
0 commit comments