diff --git a/source/dub/dub.d b/source/dub/dub.d index b6c6821..c5f0909 100644 --- a/source/dub/dub.d +++ b/source/dub/dub.d @@ -1182,17 +1182,56 @@ private void determineDefaultCompiler() { - import std.range : front; + import std.file : thisExePath; + import std.path : buildPath, dirName, expandTilde, isAbsolute, isDirSeparator; import std.process : environment; + import std.range : front; + import std.regex : ctRegex, matchFirst; - m_defaultCompiler = m_config.defaultCompiler; - if (m_defaultCompiler.length) return; + m_defaultCompiler = m_config.defaultCompiler.expandTilde; + if (m_defaultCompiler.length && m_defaultCompiler.isAbsolute) + return; + + auto dubPrefix = m_defaultCompiler.matchFirst(ctRegex!(`^\$DUB_BINARY_PATH`)); + if(!dubPrefix.empty) + { + m_defaultCompiler = thisExePath().dirName() ~ dubPrefix.post; + return; + } + + if (!find!isDirSeparator(m_defaultCompiler).empty) + throw new Exception("defaultCompiler specified in a DUB config file cannot use an unqualified relative path:\n\n" ~ m_defaultCompiler ~ + "\n\nUse \"$DUB_BINARY_PATH/../path/you/want\" instead."); version (Windows) enum sep = ";", exe = ".exe"; version (Posix) enum sep = ":", exe = ""; auto compilers = ["dmd", "gdc", "gdmd", "ldc2", "ldmd2"]; + // If a compiler name is specified, look for it next to dub. + // Otherwise, look for any of the common compilers adjacent to dub. + if (m_defaultCompiler.length) + { + string compilerPath = buildPath(thisExePath().dirName(), m_defaultCompiler ~ exe); + if (existsFile(compilerPath)) + { + m_defaultCompiler = compilerPath; + return; + } + } + else + { + auto nextFound = compilers.find!(bin => existsFile(buildPath(thisExePath().dirName(), bin ~ exe))); + if (!nextFound.empty) + { + m_defaultCompiler = buildPath(thisExePath().dirName(), nextFound.front ~ exe); + return; + } + } + // If nothing found next to dub, search the user's PATH, starting + // with the compiler name from their DUB config file, if specified. + if (m_defaultCompiler.length) + compilers = m_defaultCompiler ~ compilers; auto paths = environment.get("PATH", "").splitter(sep).map!NativePath; auto res = compilers.find!(bin => paths.canFind!(p => existsFile(p ~ (bin~exe)))); m_defaultCompiler = res.empty ? compilers[0] : res.front; diff --git a/test/issue895-local-configuration.sh b/test/issue895-local-configuration.sh index d00bb62..9799288 100755 --- a/test/issue895-local-configuration.sh +++ b/test/issue895-local-configuration.sh @@ -1,11 +1,6 @@ #!/usr/bin/env bash . $(dirname "${BASH_SOURCE[0]}")/common.sh -cd ${CURR_DIR} -mkdir ../etc -mkdir ../etc/dub -echo "{\"defaultCompiler\": \"foo\"}" > ../etc/dub/settings.json - if [ -e /var/lib/dub/settings.json ]; then die $LINENO 'Found existing system wide DUB configuration. Aborting.' fi @@ -14,9 +9,68 @@ die $LINENO 'Found existing user wide DUB configuration. Aborting.' fi -if ! { ${DUB} describe --single issue103-single-file-package.d 2>&1 || true; } | grep -cF 'Unknown compiler: foo'; then - rm -r ../etc - die $LINENO 'DUB did not find the local configuration' +cd ${CURR_DIR} +mkdir -p ../etc/dub +echo "{\"defaultCompiler\": \"foo\"}" > ../etc/dub/settings.json +echo "Empty file named foo." > ../bin/foo + +function cleanup { + rm -r ../etc +} + +trap cleanup EXIT + +if ! { ${DUB} describe --single issue103-single-file-package.d 2>&1 || true; } | grep -cF "Unknown compiler: $(dirname $CURR_DIR)/bin/foo"; then + rm ../bin/foo + die $LINENO 'DUB did not find the local configuration with an adjacent compiler.' fi -rm -r ../etc +echo "{\"defaultCompiler\": \"$CURR_DIR/foo\"}" > ../etc/dub/settings.json +mv ../bin/foo $CURR_DIR + +if ! { ${DUB} describe --single issue103-single-file-package.d 2>&1 || true; } | grep -cF "Unknown compiler: $CURR_DIR/foo"; then + rm $CURR_DIR/foo + die $LINENO 'DUB did not find a locally-configured compiler with an absolute path.' +fi + +echo "{\"defaultCompiler\": \"~/.dub/foo\"}" > ../etc/dub/settings.json +mv $CURR_DIR/foo ~/.dub/ + +if ! { ${DUB} describe --single issue103-single-file-package.d 2>&1 || true; } | grep -cF "Unknown compiler: "; then + rm ~/.dub/foo + die $LINENO 'DUB did not find a locally-configured compiler with a tilde-prefixed path.' +fi + +echo "{\"defaultCompiler\": \"\$DUB_BINARY_PATH/../foo\"}" > ../etc/dub/settings.json +mv ~/.dub/foo .. + +if ! { ${DUB} describe --single issue103-single-file-package.d 2>&1 || true; } | grep -cF "Unknown compiler: $(dirname $CURR_DIR)/bin/../foo"; then + rm ../foo + die $LINENO 'DUB did not find a locally-configured compiler with a DUB-relative path.' +fi + +echo "{\"defaultCompiler\": \"../foo\"}" > ../etc/dub/settings.json + +if ! { ${DUB} describe --single issue103-single-file-package.d 2>&1 || true; } | grep -cF "defaultCompiler specified in a DUB config file cannot use an unqualified relative path"; then + rm ../foo + die $LINENO 'DUB did not error properly for a locally-configured compiler with a relative path.' +fi + +rm ../etc/dub/settings.json +echo "Empty file named ldc2." > ../bin/ldc2 + +if ! { ${DUB} describe --single issue103-single-file-package.d 2>&1 || true; } | grep -cF "Failed to invoke the compiler $(dirname $CURR_DIR)/bin/ldc2 to determine the build platform"; then + rm ../bin/ldc2 + die $LINENO 'DUB did not find ldc2 adjacent to it.' +fi + +echo "{\"defaultCompiler\": \"foo\"}" > ../etc/dub/settings.json +rm ../bin/ldc2 +export PATH=$(dirname $CURR_DIR)${PATH:+:$PATH} + +if ! { ${DUB} describe --single issue103-single-file-package.d 2>&1 || true; } | grep -cF "Unknown compiler: foo"; then + rm ../foo + die $LINENO 'DUB did not find a locally-configured compiler in its PATH.' +fi + +rm ../foo