package com.siberika.idea.pascal.jps.sdk; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.SystemInfo; import com.siberika.idea.pascal.jps.util.FileUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.File; import java.util.regex.Pattern; /** * Author: George Bakhtadze * Date: 09/05/2014 */ public class PascalSdkUtil { public static final Logger LOG = Logger.getInstance(PascalSdkUtil.class.getName()); public static final String FPC_PARAMS_VERSION_GET = "-iV"; public static final String FPC_PARAMS_TARGET_GET = "-iTPTO"; public static final String DELPHI_PARAMS_VERSION_GET = "--version"; public static final Pattern FPC_VERSION_PATTERN = Pattern.compile("\\d+\\.\\d+\\.\\d+"); public static final String[] DEFAULT_BIN_UNIX = {"/usr/bin", "/usr/local/bin"}; public static String target; @NotNull public static File getFPCExecutable(@NotNull final String sdkHome) { LOG.info("Getting executable: " + sdkHome); return getFPCUtilExecutable(sdkHome, "bin", "fpc"); } @NotNull public static File getPPUDumpExecutable(@NotNull final String sdkHome) { LOG.info("Getting ppudump: " + sdkHome); return getFPCUtilExecutable(sdkHome, "bin", "ppudump"); } public static File getDCC32Executable(@NotNull final String sdkHome) { File binDir = new File(sdkHome, "bin"); return getExecutable(binDir.getAbsolutePath(), "dcc32"); } //TODO: take target directory from compiler target /* /$dir/ /$ver/$dir/ /$ver => $default => $bindir/[$target]/$exe */ @NotNull static File getFPCUtilExecutable(@NotNull final String sdkHome, @NotNull final String dir, @NotNull final String exe) { LOG.info("Getting util executable: " + sdkHome + ", dir: " + dir + ", file: " + exe); File binDir = new File(sdkHome, dir); File sdkHomeDir = new File(sdkHome); if (!binDir.exists() && sdkHomeDir.isDirectory()) { LOG.info(binDir.getAbsolutePath() + " not found, trying $SDKHome/$Version/bin/..."); String currentVersion = getFPCVersionDir(sdkHomeDir); if (currentVersion != null) { binDir = new File(new File(sdkHome, currentVersion), dir); if (!binDir.exists()) { LOG.info(binDir.getAbsolutePath() + " not found, trying without $SDKHome/$Version/..."); binDir = new File(sdkHome, currentVersion); } } else { binDir = sdkHomeDir; } } if (!binDir.exists() && "bin".equals(dir)) { // Default directory where fpc and ppudump executables are located LOG.info(binDir.getAbsolutePath() + " not found, trying default executable path..."); for (String defaultBinDir : DEFAULT_BIN_UNIX) { File executable = new File(defaultBinDir, exe); if (executable.exists() && executable.canExecute()) { return executable; } } LOG.info("Binary directory not found"); throw new RuntimeException("SDK not found"); } LOG.info("Binary directory found at " + binDir.getAbsolutePath()); for (File targetDir : FileUtil.listDirs(binDir)) { File executable = getExecutable(targetDir.getAbsolutePath(), exe); if (executable.canExecute()) { target = targetDir.getName(); LOG.info("Found target " + target); return executable; } } return getExecutable(binDir.getAbsolutePath(), exe); } @Nullable private static String getFPCVersionDir(File sdkHomeDir) { String currentVersion = null; for (File versionDir : FileUtil.listDirs(sdkHomeDir)) { if (isFPCVersion(versionDir.getName()) && ((currentVersion == null) || isVersionLessOrEqual(currentVersion, versionDir.getName()))) { currentVersion = versionDir.getName(); } } return currentVersion; } private static boolean isFPCVersion(String name) { return FPC_VERSION_PATTERN.matcher(name).matches(); } private static boolean isVersionLessOrEqual(String version1, String version2) { return version1.compareTo(version2) <= 0; } @NotNull public static File getByteCodeCompilerExecutable(@NotNull final String sdkHome) { return getExecutable(new File(sdkHome, "bin").getAbsolutePath(), "ppcjvm"); } @NotNull private static File getExecutable(@NotNull final String path, @NotNull final String command) { return new File(path, SystemInfo.isWindows ? command + ".exe" : command); } }