blob: 4a0aec2207e739a980b50af0336b3dbb80de7b8d [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010, 2016 Nokia Siemens Networks Oyj, Finland.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Nokia Siemens Networks - initial implementation
* Leo Hippelainen - Initial implementation
* Petri Tuononen - Initial implementation
* Marc-Andre Laperle (Ericsson)
*******************************************************************************/
package org.eclipse.cdt.managedbuilder.llvm.ui;
import java.io.File;
import java.util.HashMap;
import org.eclipse.cdt.internal.core.MinGW;
import org.eclipse.cdt.managedbuilder.core.IConfiguration;
import org.eclipse.cdt.managedbuilder.envvar.IBuildEnvironmentVariable;
import org.eclipse.cdt.managedbuilder.envvar.IConfigurationEnvironmentVariableSupplier;
import org.eclipse.cdt.managedbuilder.envvar.IEnvironmentVariableProvider;
import org.eclipse.cdt.managedbuilder.gnu.cygwin.GnuCygwinConfigurationEnvironmentSupplier;
import org.eclipse.cdt.managedbuilder.gnu.mingw.MingwEnvironmentVariableSupplier;
import org.eclipse.cdt.managedbuilder.llvm.ui.preferences.LlvmPreferenceStore;
import org.eclipse.cdt.managedbuilder.llvm.util.Separators;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
/**
* Contains LLVM environment variables.
*
* @noextend This class is not intended to be subclassed by clients.
*/
public class LlvmEnvironmentVariableSupplier implements IConfigurationEnvironmentVariableSupplier {
// toggle for preference changes
private static boolean preferencesChanged = true;
// LLVM environment variable data structure
private static HashMap<String, LlvmBuildEnvironmentVariable> llvmEnvironmentVariables = new HashMap<>(6);
// Environment variables for HashMap usage
private static final String ENV_VAR_NAME_LLVM_BIN = "LLVM_BIN_PATH"; //$NON-NLS-1$
private static final String ENV_VAR_NAME_LLVMINTERP = "LLVMINTERP"; //$NON-NLS-1$
private static final String ENV_VAR_NAME_PATH = "PATH"; //$NON-NLS-1$
private static final String ENV_VAR_NAME_INCLUDE_PATH = "INCLUDE_PATH"; //$NON-NLS-1$
private static final String ENV_VAR_NAME_LIBRARY_PATH = "LLVM_LIB_SEARCH_PATH"; //$NON-NLS-1$
private static final String ENV_VAR_NAME_LIBRARIES = "LIBRARIES"; //$NON-NLS-1$
/**
* Initializes llvm environment variable paths from the system environment variables.
*/
public static void initializePaths() { //TODO: Is this actually called anywhere?
// get bin path
String binPath = getBinPath();
// set LLVM bin path environment variable
setLlvmEnvironmentVariableReplace(ENV_VAR_NAME_LLVM_BIN, binPath);
// if bin path exists
if (binPath != null && binPath.length() != 0) {
String pathStr = binPath;
// if OS is Windows (Windows specific settings)
if (System.getProperty("os.name").toLowerCase().indexOf("win") >= 0) { //$NON-NLS-1$ //$NON-NLS-2$
try {
// try to find mingw or cygwin path from PATH environment variable
IBuildEnvironmentVariable envPath = llvmEnvironmentVariables.get(ENV_VAR_NAME_PATH);
IBuildEnvironmentVariable mingwPath = null, cygwinPath = null;
// if path is empty
if (envPath == null) {
// try to find mingw path from MingwEnvironmentVariableSupplier
IConfigurationEnvironmentVariableSupplier mingwEnvironmentVariables = new MingwEnvironmentVariableSupplier();
mingwPath = mingwEnvironmentVariables.getVariable(ENV_VAR_NAME_PATH, null, null);
// try to find cygwin path from GnuCygwinConfigurationEnvironmentSupplier
IConfigurationEnvironmentVariableSupplier cygwinEnvironmentVariables = new GnuCygwinConfigurationEnvironmentSupplier();
cygwinPath = cygwinEnvironmentVariables.getVariable(ENV_VAR_NAME_PATH, null, null);
}
// if mingw found
if (mingwPath != null) {
//form full path
pathStr = pathStr + System.getProperty("path.separator") + mingwPath.getValue(); //$NON-NLS-1$
}
// if cygwin found
if (cygwinPath != null) {
//form full path
pathStr = pathStr + System.getProperty("path.separator") + cygwinPath.getValue(); //$NON-NLS-1$
}
} catch (Exception e) {
//TODO: Emit proper error message and enter it to Eclipse error log.
e.printStackTrace();
}
}
//initialize environment variable cache values
setLlvmEnvironmentVariable(ENV_VAR_NAME_PATH, pathStr);
setLlvmEnvironmentVariable(ENV_VAR_NAME_LLVMINTERP, binPath + Separators.getFileSeparator() + "lli"); //$NON-NLS-1$
setLlvmEnvironmentVariable(ENV_VAR_NAME_INCLUDE_PATH, getSysEnvPath(ENV_VAR_NAME_INCLUDE_PATH));
setLlvmEnvironmentVariable(ENV_VAR_NAME_LIBRARY_PATH, getSysEnvPath(ENV_VAR_NAME_LIBRARY_PATH));
setLlvmEnvironmentVariable(ENV_VAR_NAME_LIBRARIES, getSysEnvPath(ENV_VAR_NAME_LIBRARIES));
preferencesChanged = false;
}
}
/**
* Returns LLVM bin path
*
* @return LLVM bin path
*/
public static String getBinPath() {
return findBinDir(ENV_VAR_NAME_LLVM_BIN, "bin"); //$NON-NLS-1$
}
/**
* Returns LLVM include paths
*
* @return LLVM include paths
*/
public static String getIncludePath() {
return getLlvmEnvironmentVariable(ENV_VAR_NAME_INCLUDE_PATH).getValue();
}
/**
* Returns LLVM library paths
*
* @return LLVM library paths
*/
public static String getLibraryPath() {
return getLlvmEnvironmentVariable(ENV_VAR_NAME_LIBRARY_PATH).getValue();
}
/**
* Returns LLVM libraries
*
* @return LLVM libraries
*/
public static String getLibraries() {
return getLlvmEnvironmentVariable(ENV_VAR_NAME_LIBRARIES).getValue();
}
/**
* Sets path to LLVM bin.
*
* @param path Path to LLVM bin location.
*/
public static void setBinPath(String path) {
setLlvmEnvironmentVariableReplace(ENV_VAR_NAME_LLVM_BIN, path);
}
/**
* Appends a new include path.
*
* @param path Include path
*/
public static void addIncludePath(String path) {
String existingIncPaths = getIncludePath();
//add the include path only if it doesn't already exists
if (!existingIncPaths.contains(path)) {
appendLlvmEnvironmentVariable(ENV_VAR_NAME_INCLUDE_PATH, existingIncPaths, path);
}
}
/**
* Appends a new library path.
*
* @param path Library path
*/
public static void addLibraryPath(String path) {
String existingLibPaths = getLibraryPath();
//add the library path only if it doesn't already exists
if (!existingLibPaths.contains(path)) {
appendLlvmEnvironmentVariable(ENV_VAR_NAME_LIBRARY_PATH, existingLibPaths, path);
}
}
/**
* Appends a new library.
*
* @param lib Library file
*/
public static void addLibrary(String lib) {
String existingLibs = getLibraries();
//add the library only if it doesn't already exists
if (!existingLibs.contains(lib)) {
appendLlvmEnvironmentVariable(ENV_VAR_NAME_LIBRARIES, existingLibs, lib);
}
}
/**
* This is to be called if some of the preference paths have changed.
*/
public static void notifyPreferenceChange() { //TODO: Change
preferencesChanged = true;
}
/**
* Returns a specific path for given parameters.
*
* @param pathKey Path for specific location
* @param subDirName Additional sub-path
* @return bin path
*/
private static String findBinDir(String pathKey, String subDirName) {
String resultPath = null;
// If preferences haven't been changed, try to find the bin path from the LLVM environment
// variable map.
if (!preferencesChanged) { //TODO: Change
//get current path
LlvmBuildEnvironmentVariable earlierValue = llvmEnvironmentVariables.get(pathKey);
//if earlier LlvmBuildEnvironmentVariable exists
if (null != earlierValue) {
//return current path
return earlierValue.getValue();
}
} else {
// Try if the path is set in the LLVM plug-in preferences
String preferenceLocation = LlvmPreferenceStore.getBinPath();
// if preference exists
if (null != preferenceLocation) {
// remove white spaces from preference location
preferenceLocation = preferenceLocation.trim();
// if preference location is not empty
if (preferenceLocation.length() != 0) {
// get path for LLVM executable
resultPath = getDirIfLlvmFound(preferenceLocation, null);
// if LLVM executable path doesn't exist
if (null == resultPath) {
// If no luck check next with sub directory name appended
resultPath = getDirIfLlvmFound(preferenceLocation, subDirName);
}
}
}
if (null == resultPath) {
// If still no luck try all folders listed in PATH
String pathVariable = System.getenv(ENV_VAR_NAME_PATH);
// split paths to String array
String[] paths = pathVariable.split(Separators.getPathSeparator());
// check every path if LLVM executable is found
for (String pathStr : paths) {
resultPath = getDirIfLlvmFound(pathStr, null);
// stop loop if LLVM executable path is found
if (null != resultPath) {
break;
}
}
}
// return found path
return resultPath;
}
return null;
}
/**
* Returns LLVM executable path.
*
* @param candidatePath Suggestion for LLVM executable path
* @param subPath Additional sub-path for LLVM executable path
* @return Full path for LLVM executable if valid, otherwise null
*/
private static String getDirIfLlvmFound(String candidatePath, String subPath) {
String llvmPath = candidatePath;
// If there is a trailing / or \, remove it
if (llvmPath.endsWith(Separators.getFileSeparator()) && llvmPath.length() > 1) {
llvmPath = llvmPath.substring(0, candidatePath.length() - 1);
}
// If subPath exists and is not empty -> append it to candidatePath.
if (null != subPath && !subPath.isEmpty()) {
// Form full path.
llvmPath = llvmPath + Separators.getFileSeparator() + subPath;
}
// Return a full path for LLVM executable if it's valid, otherwise null.
return getBinDirIfLlvm_ar(llvmPath);
}
/**
* Returns the full path for llvm executable if the bin path given
* as a parameter is found and executable exists in that path.
*
* @param binPathTemp User provided bin directory path
* @return bin path where llvm-ar is located if executable exists
*/
private static String getBinDirIfLlvm_ar(String binPathTemp) {
//if given directory is found
if (new Path(binPathTemp).toFile().isDirectory()) {
String llvm_executable = "llvm-ar"; //$NON-NLS-1$
File arFileFullPath = null;
// If OS is Windows -> add .exe to the executable name.
if (System.getProperty("os.name").toLowerCase().indexOf("win") >= 0) { //$NON-NLS-1$//$NON-NLS-2$
llvm_executable = llvm_executable + ".exe"; //$NON-NLS-1$
}
// Form full executable path
arFileFullPath = new File(binPathTemp, llvm_executable);
// Check if file exists -> proper LLVM installation exists.
if (arFileFullPath.isFile()) {
// Return path where llvm-ar exists.
return binPathTemp;
}
}
return null;
}
/**
* @return location of $MINGW_HOME/bin folder on the file-system.
* @deprecated. Deprecated as of CDT 8.2. Note that MinGW root path in general may depend on configuration.
*
* If you use this do not cache results to ensure user preferences are accounted for.
* Please rely on internal caching.
*/
@Deprecated
private static IPath getBinDir() {
IPath binDir = null;
String minGWHome = MinGW.getMinGWHome();
if (minGWHome != null) {
binDir = new Path(minGWHome).append("bin"); //$NON-NLS-1$
}
return binDir;
}
/**
* Returns stdc++ library path located in MinGW installation.
*
* @return stdc++ library path for MinGW
*/
public static String getMinGWStdLib() {
// get mingw bin path
IPath mingwBinPath = getBinDir();
if (mingwBinPath != null) {
StringBuilder sB = new StringBuilder(mingwBinPath.toOSString());
// drop bin
if (sB.length() >= 3) {
sB.delete(sB.length() - 3, sB.length());
// append mingw lib subdir
sB.append("lib\\gcc\\mingw32\\"); //$NON-NLS-1$
// get all files in the directory
File f = new File(sB.toString());
if (f.isDirectory()) {
String[] list = f.list();
if (list.length > 0) {
// append the first dir
sB.append(list[0]);
return sB.toString();
}
}
}
}
return null;
}
/**
*
* Returns LLVM environment variable.
*
* @param envName Name of the environment variable
*/
public static LlvmBuildEnvironmentVariable getLlvmEnvironmentVariable(String envName) {
return llvmEnvironmentVariables.get(envName);
}
/**
* Sets LLVM environment variable.
*
* @param name Name for the environment variable
* @param path Path for the environment variable
*/
private static void setLlvmEnvironmentVariable(String name, String path) {
// append a new path in front of the the old path in HashMap that contains
// the specific LLVM environment variable
llvmEnvironmentVariables.put(name,
new LlvmBuildEnvironmentVariable(name, path, IBuildEnvironmentVariable.ENVVAR_APPEND));
}
/**
* Sets LLVM environment variable by replacing the existing paths.
*
* @param name Name for the environment variable
* @param path Path for the environment variable
*/
public static void setLlvmEnvironmentVariableReplace(String name, String path) {
// replace the old path in HashMap that contains the specific LLVM environment variable
llvmEnvironmentVariables.put(name,
new LlvmBuildEnvironmentVariable(name, path, IBuildEnvironmentVariable.ENVVAR_REPLACE));
}
/**
* Appends a new LLVM environment variable to existing list.
*
* @param name Name of the preference
* @param oldPath Old paths/preference values
* @param path New path to be added to the environment variable
*/
public static void appendLlvmEnvironmentVariable(String name, String oldPath, String path) {
String newPath = null;
boolean ok = false;
// if oldPath exists
if (oldPath != null) {
//if the oldPath isn't empty
if (!oldPath.trim().isEmpty()) {
StringBuilder sB = new StringBuilder();
// append old path
sB.append(oldPath);
// append a path separator
sB.append(Separators.getPathSeparator());
// append the new path
sB.append(path);
// construct a new full path
newPath = sB.toString();
ok = true;
}
}
if (!ok) {
newPath = path;
}
// Set new path to the HashMap that contains the specific LLVM environment variable
// if newPath exists.
if (newPath != null) {
// if the newPath isn't empty
if (!newPath.trim().isEmpty()) {
// add new values to the LLVM environment variable
llvmEnvironmentVariables.put(name,
new LlvmBuildEnvironmentVariable(name, newPath, IBuildEnvironmentVariable.ENVVAR_APPEND));
}
}
}
/**
* Returns a system environment variable path
*
* @param envName Environment variable name
* @return system environment variable path
*/
private static String getSysEnvPath(String envName) {
String path = System.getenv(envName);
if (path != null) {
return path;
}
return ""; //$NON-NLS-1$
}
@Override
public IBuildEnvironmentVariable getVariable(String variableName, IConfiguration configuration,
IEnvironmentVariableProvider provider) {
return llvmEnvironmentVariables.get(variableName);
}
@Override
public IBuildEnvironmentVariable[] getVariables(IConfiguration configuration,
IEnvironmentVariableProvider provider) {
return llvmEnvironmentVariables.values().toArray(new IBuildEnvironmentVariable[0]);
}
}