Arduino IDE multiple profiles/configurations

Greetings,

I recently had an issue with configuring Seeed XIAO to run the Joystick 2.0 library. With guidance from here and digging on the internet I finally solved the issue. However, the solution prevented me from running the library on any other model of boards.

Searched the internet and the forums here. Solution were go back to Arduino IDE 1.xx and run a portable set version or modify the IDE configuration each time I changed board/project. There were a few request for change to add this type of feature since about 2015, but don't see it happening anytime soon.

So I decided to write a bash script to do what I needed for use on Linux. Does not work on Windows. Don't have a Mac to try it on. May work or need a bit of tweaking to get it to run.

Below is the script I came up. Releasing it to the community to use as they see fit.

It works by by moving the Arduino folders from there normally installed location to a folder named "ArduinoProfile" within the user's home folder. Each profile is given it own folder within it. i.e. ArduinoProfile/Default.

Links are then placed at the original Adruino folder locations pointing to the current profile.
Folders are:

  • User'sHomeFolder/.arduino15
  • User'sHomeFolder/.arduinoIDE
  • User'sHomeFolder/.config/Arduino IDE
  • User'sHomeFolder/.config/arduino-ide
  • User'sHomeFolder/Arduino

This allows each profile to be a fully self contained environment with only the files and libraries needed. You can have profiles for board type or for each project, any way you choose. This prevents libraries from conflicting.

Features include:

  • Creating a new empty profile. Arduino IDE will automatically fill it on its first run.
  • Clone an existing profile. No need reconfigure a default setup.
  • Delete a profile. Deleted profile are permanently deleted. Use with care.
  • Switch profiles. Cannot/should be done while Arduino IDE is running. Will cause data corruption.

Must be run in console window.
Tested on Kubuntu 23.4.

#!/bin/bash
# Author: Randy S. Bancroft
# Date: June 12, 2023
#
# I make no guarantees for this script.
# Use at your own risk.
#
# Allows the use of multiple profiles/configurations of the Arduino IDE 2.xx.
# You can only run one profile at a time.
# You can run multiple instances of the same profile.
#
# It does so by by moving the Arduino folders from there normally installed
# location to a folder named "ArduinoProfile" within the user's home folder.
# Each profile is given it own folder within it. i.e. ArduinoProfile/Default.
# Links are then placed at the original Adruino folder locations pointing to
# the current profile.
# Folders are:
# - User'sHomeFolder/.arduino15
# - User'sHomeFolder/.arduinoIDE
# - User'sHomeFolder/.config/Arduino IDE
# - User'sHomeFolder/.config/arduino-ide
# - User'sHomeFolder/Arduino
# This allows each profile to be a fully self contained environment with only
# the files and libraries needed.
# You can have folders for board type or for each project, any way you choose.
# This prevents libraries from conflicting.
# Features include:
# - Creating a new empty profile.  Arduino IDE will automatically fill it on
#   its first run.
# - Clone an existing profile.  No need reconfigure a default setup.
# - Delete a profile.  Deleted profile are permanently deleted.  Use with care.
# - Switch profiles.  Cannot/should be done while Arduino IDE is running.
#   Will cause data corruption.
#
# This script is free to use/modify/distribute as you desire.

START_UP_DIR=`PWD`
HOME=~
IDE_NAME="arduino-ide_2.1.0_Linux_64bit.AppImage"
IDE_PATH="${HOME}/Desktop/"
START_IDE="0" # 1 launches Arduino IDE after selecting profile.  Ensure IDE_PATH and IDE_NAME are correct.
PROFILE="Default"
NUMBER_OF_DIRS=""
LINK=""
CURRENT_PROFILE=""
YN="n"

function list_profiles {
    for i in "${!userarr[@]}"; do
    echo $i ${userarr[$i]%*/}
    done
    NUMBER_OF_DIRS="${#userarr[@]}"
}

function change_profile {

    rm -rf "${HOME}/.arduino15"
    rm -rf "${HOME}/.arduinoIDE"
    rm -rf "${HOME}/.config/Arduino IDE"
    rm -rf "${HOME}/.config/arduino-ide"
    rm -rf "${HOME}/Arduino"

    ln -sf "${HOME}/ArduinoProfile/${1}/.arduino15" "${HOME}/.arduino15"
    ln -sf "${HOME}/ArduinoProfile/${1}/.arduinoIDE" "${HOME}/.arduinoIDE"
    ln -sf "${HOME}/ArduinoProfile/${1}/Arduino" "${HOME}/Arduino"
    ln -sf "${HOME}/ArduinoProfile/${1}/.config/arduino-ide" "${HOME}/.config/arduino-ide"
    ln -sf "${HOME}/ArduinoProfile/${1}/.config/Arduino IDE" "${HOME}/.config/Arduino IDE"
    echo Arduino IDE will now use profile "#"$2 "("$1")"
    if [ $START_IDE == 1 ]
        then
            launch_ide
    fi
}

function create_new_profile {
    if [ $1 == Default ]
        then
            NEW_PROFILE=$1
        else
            reset
            echo Enter name of new profile or press \"Enter\" to exit:
            read NEW_PROFILE

            is_it_alphanumeric "$NEW_PROFILE"
    fi

    if [ ! -d "$HOME/ArduinoProfile/$NEW_PROFILE" ]
        then
            echo make new dirs "${HOME}/ArduinoProfile/${NEW_PROFILE}" # testing
            mkdir -p "${HOME}/ArduinoProfile/${NEW_PROFILE}"
            mkdir -p "${HOME}/ArduinoProfile/${NEW_PROFILE}/.arduino15"
            mkdir -p "${HOME}/ArduinoProfile/${NEW_PROFILE}/.arduinoIDE"
            mkdir -p "${HOME}/ArduinoProfile/${NEW_PROFILE}/.config/Arduino IDE"
            mkdir -p "${HOME}/ArduinoProfile/${NEW_PROFILE}/.config/arduino-ide"
            mkdir -p "${HOME}/ArduinoProfile/${NEW_PROFILE}/Arduino"
            SELECTION=$NEW_PROFILE
            reset
            echo Profile \"$NEW_PROFILE\" created and ready for use!
            echo
            echo This is a blank profile and will be configuered
            echo the first time Arduino IDE is run...
            change_profile $NEW_PROFILE
    else
        if [ $NEW_PROFILE == Default ]
            then
                change_profile $NEW_PROFILE
            else
                echo Profile \"$NEW_PROFILE\" already exist!
                sleep 5
                exit
        fi
    fi
}

function delete_profile {
    echo Delete Profile $1
    yes_or_no
    if [ $? == 1 ]
        then
            change_profile Default
            rm -rf $HOME/ArduinoProfile/$1
            echo Profile \"$1\" deleted...
    fi
}

function is_ide_already_running {
    if pidof arduino-ide > /dev/null
        then
            PIDS=`pidof arduino-ide`
            PIDS="${PIDS} `pidof arduino-cli`"
            echo Arduino IDE is running!
            echo Cannot change profile while IDE is running.
            echo Please close Arduino IDE and rerun this script.
            echo
            echo If you are sure Arduino IDE is not running
            echo you have zombie process.
            echo
            echo " ........."
            echo " ;(6) (o);"
            echo " \\   \"   "/""
            echo "  ( HHH )"
            echo "  _)   (_"
            echo ".'  '-'  '''---.._"
            echo ": .     .--''''CCD"
            echo ": :_____:    C(+,+)D"
            echo "/_:___Z_:      (-)"
            echo "((|     |"
            echo "  .  :  :"
            echo "  /  |  |"
            echo " ;  / ; /"
            echo " L_)  [_7"
            echo
            echo Kill the zombies...
            yes_or_no
            if [ $? == 1 ]
                then
                    kill ${PIDS}
                    echo Killing zombies... uugh
                    echo Please wait...
                    echo "     ___"
                    sleep 1
                    echo "  ,-'RIP'-,"
                    sleep 1
                    echo "  | .---. |"
                    sleep 1
                    echo "  |( # # )_\|/_"
                    sleep 1
                    echo "  | | # | | /"
                    sleep 1
                    echo "  | :+++: |/"
                    sleep 1
                    echo "  |   |   /"
                    sleep 1
                    echo "\"\"\"\"\"\"\"\"\"\"\"\"\"\""
                    sleep 2
            else
                echo Leave the zombies be...
                sleep 3
                exit
            fi
    fi
}

function yes_or_no {
    read -p "Do you want to proceed? (yes/no) " yes_no

    case $yes_no in
        yes )
            echo Yes!  Proceeding as directed...;
            return 1;;
        YES )
            echo Yes!  Proceeding as directed...;
            return 1;;
        Yes )
            echo Yes!  Proceeding as directed...;
            return 1;;
        yES )
            echo Yes!  Proceeding as directed...;
            return 1;;
        y )
            echo Yes!  Proceeding as directed...;
            return 1;;
        Y )
            echo Yes!  Proceeding as directed...;
            return 1;;
        no )
            echo No!  Exiting...;
            return 0;;
        NO )
            echo No!  Exiting...;
            return 0;;
        No )
            echo No!  Exiting...;
            return 0;;
        nO )
            echo No!  Exiting...;
            return 0;;
        n )
            echo No!  Exiting...;
            return 0;;
        N )
            echo No!  Exiting...;
            return 0;;
        * )
            invalid_exit;;
    esac
}

function is_it_blank {
    # if no input exit
    if [ -z "$1" ]
        then
            echo Blank input!  Exiting...
            sleep 5
            exit
        else
            return 1
    fi
}

function is_it_alphanumeric {
    is_it_blank $1
    if [[ ! $1 =~ ^['a-zA-Z0-9. ']+$ ]]
        then
            reset
            echo Input contained invalid characters!
            echo
            echo Upper and lower case letters, numbers,
            echo period and space only.
            echo
            echo Exiting....
            sleep 5
            exit
    fi
}

function is_it_numeric {
    is_it_blank $1
    if [[ ! $1 =~ ^['0-9']+$ ]]
        then
            reset
            echo Input contained invalid characters!
            echo
            echo Numbers only.
            echo
            echo Exiting....
            sleep 5
            exit
    fi
}

function invalid_exit {
    echo Invalid entry!  Exiting...
    sleep 5
    exit
}

function set_up_profiles {
    echo Not configured to use profiles.
    echo
    if [ $1 == profile_exist ]
        then
            echo Existing Arduino IDE configuration found.
            echo Continuing will set up profiles and place
            echo existing configuration in the \"Default\"
            echo profile.
            echo
    fi
    echo Setup profiles:
    yes_or_no
    YN=$?
    if [ $YN == 1 ] && [ $1 == profile_not_exist ] # yes
        then
            create_new_profile Default
    elif [ $YN == 1 ] && [ $1 == profile_exist ]
            then
                mkdir -p "${HOME}/ArduinoProfile/Default"
                mkdir -p "${HOME}/ArduinoProfile/Default/.arduino15"
                mkdir -p "${HOME}/ArduinoProfile/Default/.arduinoIDE"
                mkdir -p "${HOME}/ArduinoProfile/Default/.config/Arduino IDE"
                mkdir -p "${HOME}/ArduinoProfile/Default/.config/arduino-ide"
                mkdir -p "${HOME}/ArduinoProfile/Default/Arduino"

                mv -f "${HOME}/.arduino15" "${HOM}E/ArduinoProfile/Default"
                mv -f "${HOME}/.arduinoIDE" "${HOME}/ArduinoProfile/Default"
                mv -f "${HOME}/.config/Arduino IDE" "${HOME}/ArduinoProfile/Default/.config"
                mv -f "${HOME}/.config/arduino-ide" "${HOME}/ArduinoProfile/Default/.config"
                mv -f "${HOME}/Arduino" "${HOME}/ArduinoProfile/Default"
                change_profile Default

    fi
}

function launch_ide {
    nohup $IDE_PATH$IDE_NAME &
    disown
    sleep 5
    exit
}

function clone_profile {
    reset
    list_profiles
    echo
    echo Enter number for profile to be cloned...
    read CLONE
    is_it_numeric "$CLONE"

    SOURCE_NAME=${userarr[$CLONE]%*/}
    echo Cloning profile \"$SOURCE_NAME\"
    echo
    echo Enter name for cloned profile or press \"Enter\" to exit:

    read NEW_PROFILE
    is_it_alphanumeric "$NEW_PROFILE"

    echo
    echo Cloning profile \"$SOURCE_NAME\" to new profile \"$NEW_PROFILE\"
    YN=0
    yes_or_no
    YN=$?
    if [ $YN == 1 ]
        then
            if [ -d "${HOME}/ArduinoProfile/${NEW_PROFILE}" ]
                then
                    echo Profile \"$NEW_PROFILE\" already exist!
                    echo
                    YN=0
                    yes_or_no
                    YN=$?
                    if [ $YN == 1 ]
                        then
                            rm -Rf "${HOME}/ArduinoProfile/${NEW_PROFILE}"
                    else
                        Aborting....
                        sleep 5
                    fi

        fi
        cp -Rf "${HOME}/ArduinoProfile/${SOURCE_NAME}" "${HOME}/ArduinoProfile/${NEW_PROFILE}"
        echo Profile \"$SOURCE_NAME\" cloned to \"$NEW_PROFILE\"...
    fi

}

function get_current_profile {
    CURRENT_PROFILE=${LINK#*${HOME}/ArduinoProfile/}
    CURRENT_PROFILE=${CURRENT_PROFILE%/Arduino*}
    if [ -z "$CURRENT_PROFILE" ]
        then
            CURRENT_PROFILE="none_in_use"
    fi
}

reset

is_ide_already_running

if [ -d "$HOME/Arduino" ]
    then
        cd ${HOME}/Arduino;
        LINK=`pwd -P`
        cd $START_UP_DIR

        if [ $LINK == ${HOME}/Arduino ]
            then
                set_up_profiles profile_exist
        fi
    else
        set_up_profiles profile_not_exist
        CURRENT_PROFILE="Default"
fi

get_current_profile

cd $HOME/ArduinoProfile
userarr=( */ );
reset
echo NOTE: Only one profile can be run at at time.
echo       Running multiple profiles at once will cause data corruption!
echo
echo       Multiple instances of the the same profile is no problem.
echo
echo Current profile is \"$CURRENT_PROFILE\"
echo
echo Enter the letter of the desire task and press enter:
echo \"n\" = create a new profile
echo \"c\" = clone an existing profile
echo \"d\" = delete a profile
echo \"s\" = switch to desired profile

read SELECTION

is_it_alphanumeric "$SELECTION"

if [ $SELECTION == "n" ] || [ $SELECTION == "N" ]
            then
                create_new_profile
    elif [ $SELECTION == "d" ] || [ $SELECTION == "D" ]
        then
            reset
            list_profiles
            echo Enter number for profile to be deleted...
            read TO_BE_DELETED
            is_it_numeric "$TO_BE_DELETED"

            if [[ $TO_BE_DELETED =~ [0-9] ]]
                then
                    TO_BE_DELETED=$(($TO_BE_DELETED + 0))
                    if [ $TO_BE_DELETED -gt $NUMBER_OF_DIRS ]
                        then
                            invalid_exit
                        else
                            delete_profile ${userarr[$TO_BE_DELETED]%*/}
                        exit
                    fi
            fi
    elif [ $SELECTION == "c" ] || [ $SELECTION == "C" ]
        then
            clone_profile
    elif [ $SELECTION == "s" ] || [ $SELECTION == "S" ]
        then
            reset
            echo Current profile is \"$CURRENT_PROFILE\"
            echo
            echo Available profiles are:
            list_profiles

            echo Enter number of profile to selected...
            read SELECTION

            is_it_numeric "$SELECTION"

            if [[ $SELECTION =~ [0-9]+$ ]]
                then
                    SELECTION=$(($SELECTION + 0))
                    if [ $SELECTION -gt $NUMBER_OF_DIRS ]
                        then
                            invalid_exit
                        else
                            PROFILE=${userarr[$SELECTION]%*/}
                            change_profile "$PROFILE" "$SELECTION"
                        exit
                    fi
            else
                invalid_exit
            fi

    else
            invalid_exit
fi

Hope this helps someone,
Randy S. Bancroft

Greetings,

I found a bug in creating new profiles with spaces in the names. It creates the profile correctly, but tries to switch to a profile with name truncated.

For example I create a profile named "pro micro". The profile is created as "pro micro", but it tries to switch to "pro".

To correct:

  • got to the function create_new_profile at line 75
  • change lines 102 and 106 from change_profile $NEW_PROFILE to change_profile "$NEW_PROFILE"

The quotes need to be added to variable $NEW_PROFILE.

Corrected function below:

function create_new_profile {
    if [ $1 == Default ]
        then
            NEW_PROFILE=$1
        else
            reset
            echo Enter name of new profile or press \"Enter\" to exit:
            read NEW_PROFILE

            is_it_alphanumeric "$NEW_PROFILE"
    fi

    if [ ! -d "$HOME/ArduinoProfile/$NEW_PROFILE" ]
        then
            echo make new dirs "${HOME}/ArduinoProfile/${NEW_PROFILE}" # testing
            mkdir -p "${HOME}/ArduinoProfile/${NEW_PROFILE}"
            mkdir -p "${HOME}/ArduinoProfile/${NEW_PROFILE}/.arduino15"
            mkdir -p "${HOME}/ArduinoProfile/${NEW_PROFILE}/.arduinoIDE"
            mkdir -p "${HOME}/ArduinoProfile/${NEW_PROFILE}/.config/Arduino IDE"
            mkdir -p "${HOME}/ArduinoProfile/${NEW_PROFILE}/.config/arduino-ide"
            mkdir -p "${HOME}/ArduinoProfile/${NEW_PROFILE}/Arduino"
            SELECTION=$NEW_PROFILE
            reset
            echo Profile \"$NEW_PROFILE\" created and ready for use!
            echo
            echo This is a blank profile and will be configured
            echo the first time Arduino IDE is run...
            change_profile "$NEW_PROFILE"
    else
        if [ $NEW_PROFILE == Default ]
            then
                change_profile "$NEW_PROFILE"
            else
                echo Profile \"$NEW_PROFILE\" already exist!
                sleep 5
                exit
        fi
    fi
}

Randy S. Bancroft

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.