Set environment variables such as PATH in bash

The are multiple ways to define environement variables such as PATH in the terminal. However, some ways may be more appropriate than others.

For the short answer: set the environment variables in ~/.profile.

Now, the long answer. It is common to define variables in ~/.bashrc, however it has some disavantages. The latter file is read by bash, and only if the shell is interactive and non-login[1]. The login script ~/.profile is the one originally used by /bin/sh[2][3], so it is compatible with more shells.

Files related to bash are described in the FILES section of man bash[4]. In the default ~/.profile file in Debian/Ubuntu distribution, you can read:

# ~/.profile: executed by the command interpreter for login shells.
# This file is not read by bash(1), if ~/.bash_profile or ~/.bash_login
# exists.

Thus, if ~/.bash_profile exists, you may want to include the instructions from ~/.profile as well. To do so, you can add the following to .bash_profile[5]:

if [ -r ~/.profile ]; then . ~/.profile; fi

To compile and install libraries in my home directory, I used to create a ~/.local folder that is analog to /usr/local. I want to have the same structure, with bin, include, lib folders, and recognized in the same way. This is possible by adding the following content in ~/.profile:

# ~/.local
# PATH="$HOME/.local/bin:$PATH"
CPATH="$HOME/.local/include:$CPATH"
C_INCLUDE_PATH="$HOME/.local/include:$C_INCLUDE_PATH"
CPLUS_INCLUDE_PATH="$HOME/.local/include:$CPLUS_INCLUDE_PATH"
LIBRARY_PATH="$HOME/.local/lib:$LIBRARY_PATH"
LD_LIBRARY_PATH="$HOME/.local/lib:$LD_LIBRARY_PATH"

Some remarks on environment variables[6][7]:

  • CPATH tells gcc where to search for both C and C++ header files.
  • C_INCLUDE_PATH tells gcc where to search for C header files.
  • CPLUS_INCLUDE_PATH tells gcc where to search for C++ header files.
  • LIBRARY_PATH is used by gcc before compilation to find directories containing static and shared libraries to be linked.
  • LD_LIBRARY_PATH is used by programs to find directories containing shared libraries.

Note that this applies also to clang[8]. I commented the line defining PATH because $HOME/.local/bin was already added in the default configuration of Debian/Ubuntu. It is not necessary to export PATH since it is enough that it is exported once and it can add complications on shells other than bash[9]. For other variables such as CPATH, I had to use export, so I added the following to ~/.profile.

export CPATH
export C_INCLUDE_PATH
export CPLUS_INCLUDE_PATH
export LIBRARY_PATH
export LD_LIBRARY_PATH

Softwares such as CPLEX do not follow strictly the UNIX structure when installed. No problem, I add the corresponding paths in my ~/.profile:

# CPLEX
CPLEX_PATH="/opt/ibm/ILOG/CPLEX_Studio129"
CPLEX_ARCH="x86-64_linux"
PATH="$PATH:$CPLEX_PATH/cplex/bin/$CPLEX_ARCH:$CPLEX_PATH/opl/bin/$CPLEX_ARCH"
CPATH="$CPATH:$CPLEX_PATH/cplex/include:$CPLEX_PATH/concert/include"
C_INCLUDE_PATH="$C_INCLUDE_PATH:$CPLEX_PATH/cplex/include:$CPLEX_PATH/concert/include"
CPLUS_INCLUDE_PATH="$CPLUS_INCLUDE_PATH:$CPLEX_PATH/cplex/include:$CPLEX_PATH/concert/include"
LIBRARY_PATH="$LIBRARY_PATH:$CPLEX_PATH/cplex/lib/$CPLEX_ARCH/static_pic:$CPLEX_PATH/concert/lib/$CPLEX_ARCH/static_pic"
LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$CPLEX_PATH/cplex/lib/$CPLEX_ARCH/static_pic:$CPLEX_PATH/concert/lib/$CPLEX_ARCH/static_pic"

Feel free to modify the CPLEX_PATH and CPLEX_ARCH variables according to your specific configuration.

References


  1. .bash_profile vs .bashrc - Josh Staiger ↩︎

  2. What’s the difference between .bashrc, .bash_profile, and .environment? - Stack Exchange ↩︎

  3. What are the functional differences between .profile .bash_profile and .bashrc - Stack Exchange ↩︎

  4. bash - Linux man page ↩︎

  5. Difference between .bashrc and .bash_profile - Stack Exchange ↩︎

  6. LD_LIBRARY_PATH vs LIBRARY_PATH - Stack Exchange ↩︎

  7. Environment Variables Affecting GCC ↩︎

  8. clang manual ↩︎

  9. How to correctly add a path to PATH? - Stack Exchange ↩︎