diff --git a/src/nimble.nim b/src/nimble.nim index 5eaf8009..e5c9b89f 100644 --- a/src/nimble.nim +++ b/src/nimble.nim @@ -21,7 +21,7 @@ import nimblepkg/packageinfotypes, nimblepkg/packageinfo, nimblepkg/version, nimblepkg/nimscriptwrapper, nimblepkg/developfile, nimblepkg/paths, nimblepkg/nimbledatafile, nimblepkg/packagemetadatafile, nimblepkg/displaymessages, nimblepkg/sha1hashes, nimblepkg/syncfile, - nimblepkg/deps, nimblepkg/nimblesat, nimblepkg/forge_aliases + nimblepkg/deps, nimblepkg/nimblesat, nimblepkg/forge_aliases, nimblepkg/nimenv const nimblePathsFileName* = "nimble.paths" @@ -754,35 +754,6 @@ proc processLockedDependencies(pkgInfo: PackageInfo, options: Options): return res.toHashSet -proc compileNim(realDir: string) = - let command = when defined(windows): "build_all.bat" else: "./build_all.sh" - cd realDir: - display("Info:", "compiling nim in $1" % realDir, priority = HighPriority) - tryDoCmdEx(command) - -proc useNimFromDir(options: var Options, realDir: string, tryCompiling = false) = - const binaryName = when defined(windows): "nim.exe" else: "nim" - - let - nim = realDir / "bin" / binaryName - fileExists = fileExists(options.nimBin) - - if not fileExists(nim): - if tryCompiling and options.prompt("Develop version of nim was found but it is not compiled. Compile it now?"): - compileNim(realDir) - else: - raise nimbleError("Trying to use nim from $1 " % realDir, - "If you are using develop mode nim make sure to compile it.") - - options.nimBin = nim - let separator = when defined(windows): ";" else: ":" - - putEnv("PATH", realDir / "bin" & separator & getEnv("PATH")) - if fileExists: - display("Info:", "switching to $1 for compilation" % options.nim, priority = HighPriority) - else: - display("Info:", "using $1 for compilation" % options.nim, priority = HighPriority) - proc install(packages: seq[PkgTuple], options: Options, doPrompt, first, fromLockFile: bool, preferredPackages: seq[PackageInfo] = @[]): PackageDependenciesInfo = @@ -817,6 +788,9 @@ proc install(packages: seq[PkgTuple], options: Options, var downloadPath = "" if options.useSatSolver and subdir == "": #Ignore the cache if subdir is set downloadPath = getCacheDownloadDir(url, pv.ver, options) + # if pv.name.isNim: + # downloadPath = "/Volumes/Store/Projects/nim/nimble/temptest/nimtest" + let (downloadDir, downloadVersion, vcsRevision) = if not isAlias: @@ -831,8 +805,8 @@ proc install(packages: seq[PkgTuple], options: Options, try: var opt = options if pv.name.isNim: - compileNim(downloadDir) - opt.useNimFromDir(downloadDir, true) + compileNim(opt, downloadDir, pv.ver) + opt.useNimFromDir(downloadDir, pv.ver, true) result = installFromDir(downloadDir, pv.ver, opt, url, first, fromLockFile, vcsRevision, preferredPackages = preferredPackages) @@ -2403,16 +2377,17 @@ proc setNimBin*(options: var Options) = if lockFile.fileExists and not options.disableLockFile and not options.useSystemNim: for name, dep in lockFile.getLockedDependencies.lockedDepsFor(options): if name.isNim: + let v = dep.version.toVersionRange() if isInstalled(name, dep, options): - options.useNimFromDir(getDependencyDir(name, dep, options)) + options.useNimFromDir(getDependencyDir(name, dep, options), v) elif not options.offline: let depsOnly = options.depsOnly options.depsOnly = false let downloadResult = downloadDependency(name, dep, options, false) - compileNim(downloadResult.downloadDir) - options.useNimFromDir(downloadResult.downloadDir) + compileNim(options, downloadResult.downloadDir, v) + options.useNimFromDir(downloadResult.downloadDir, v) let pkgInfo = installDependency(initTable[string, LockFileDep](), downloadResult, options, @[]) - options.useNimFromDir(pkgInfo.getRealDir) + options.useNimFromDir(pkgInfo.getRealDir, v) options.depsOnly = depsOnly break @@ -2429,13 +2404,13 @@ proc setNimBin*(options: var Options) = let installedPkgs = getInstalledPkgsMin(options.getPkgsDir(), options) var pkg = initPackageInfo() if findPkg(installedPkgs, nimVersion, pkg): - options.useNimFromDir(pkg.getRealDir) + options.useNimFromDir(pkg.getRealDir, pkg.basicInfo.version.toVersionRange()) else: # It still no nim found then download and install one to allow parsing of # other packages. if options.nimBin.len == 0 and not options.offline and options.prompt("No nim found. Download it now?"): for pkg in install(nimVersion, options): - options.useNimFromDir(pkg.getRealDir) + options.useNimFromDir(pkg.getRealDir, pkg.basicInfo.version.toVersionRange()) if options.nimBin.len == 0: raise nimbleError("Unable to find nim") @@ -2446,7 +2421,7 @@ proc setNimBin*(options: var Options) = pkgInfo = getPkgInfo(getCurrentDir(), options) for pkg in pkgInfo.processDevelopDependencies(options): if pkg.name.isNim: - options.useNimFromDir(pkg.getRealDir, true) + options.useNimFromDir(pkg.getRealDir, pkg.basicInfo.version.toVersionRange(), true) return options.pkgInfoCache.clear() except NimbleError: @@ -2464,11 +2439,11 @@ proc setNimBin*(options: var Options) = let installedPkgs = getInstalledPkgsMin(options.getPkgsDir(), options) var pkg = initPackageInfo() if findPkg(installedPkgs, require, pkg): - options.useNimFromDir(pkg.getRealDir) + options.useNimFromDir(pkg.getRealDir, require.ver) else: if not options.offline and options.prompt("No nim version matching $1. Download it now?" % $require.ver): for pkg in install(require, options): - options.useNimFromDir(pkg.getRealDir) + options.useNimFromDir(pkg.getRealDir, require.ver) else: let msg = "Unsatisfied dependency: " & require.name & " (" & $require.ver & ")" raise nimbleError(msg) diff --git a/src/nimblepkg/nimblesat.nim b/src/nimblepkg/nimblesat.nim index 7fa2ad8c..e655cbf3 100644 --- a/src/nimblepkg/nimblesat.nim +++ b/src/nimblepkg/nimblesat.nim @@ -105,22 +105,22 @@ proc hasVersion*(packagesVersions: Table[string, PackageVersions], name: string, return true false -proc getNimVersion*(pvs: seq[PkgTuple]): Version = - proc getVersion(ver: VersionRange): Version = - case ver.kind: - of verLater, verEarlier, verEqLater, verEqEarlier, verEq: - ver.ver - of verSpecial: - ver.spe - of verIntersect, verTilde, verCaret: - getVersion(ver.verILeft) - of verAny: - newVersion "0.0.0" +proc getNimVersion*(ver: VersionRange): Version = + case ver.kind: + of verLater, verEarlier, verEqLater, verEqEarlier, verEq: + ver.ver + of verSpecial: + ver.spe + of verIntersect, verTilde, verCaret: + getNimVersion(ver.verILeft) + of verAny: + newVersion "0.0.0" +proc getNimVersion*(pvs: seq[PkgTuple]): Version = result = newVersion("0.0.0") for pv in pvs: if pv.name == "nim": - result = getVersion(pv.ver) + result = getNimVersion(pv.ver) proc findDependencyForDep(g: DepGraph; dep: string): int {.inline.} = assert g.packageToDependency.hasKey(dep), dep & " not found" diff --git a/src/nimblepkg/nimenv.nim b/src/nimblepkg/nimenv.nim new file mode 100644 index 00000000..0cd61a13 --- /dev/null +++ b/src/nimblepkg/nimenv.nim @@ -0,0 +1,110 @@ +import std/[strscans, os, strutils, strformat] +import version, nimblesat, cli, common, options + +when defined(windows): + const + BatchFile = """ + @echo off + set PATH="$1";%PATH% + """ +else: + const + ShellFile = "export PATH=$1:$$PATH\n" + +const ActivationFile = + when defined(windows): "activate.bat" else: "activate.sh" + +proc infoAboutActivation(nimDest, nimVersion: string) = + when defined(windows): + display("Info", nimDest & "installed; activate with 'nim-" & nimVersion & "activate.bat'") + else: + display("Info", nimDest & "installed; activate with 'source nim-" & nimVersion & "activate.sh'") + +proc compileNim*(options: Options, nimDest: string, v: VersionRange) = + let keepCsources = options.useSatSolver #SAT Solver has a cache instead of a temp dir for downloads + template exec(command: string) = + let cmd = command # eval once + if os.execShellCmd(cmd) != 0: + display("Error", "Failed to execute: $1" % cmd, Error, HighPriority) + return + let nimVersion = v.getNimVersion() + let workspace = nimDest.parentDir() + if dirExists(workspace / nimDest): + if not fileExists(nimDest / ActivationFile): + display("Info", &"Directory {nimDest} already exists; remove or rename and try again") + else: + infoAboutActivation nimDest, $nimVersion + return + + var major, minor, patch: int + if not nimVersion.isSpecial: + if not scanf($nimVersion, "$i.$i.$i", major, minor, patch): + display("Error", "cannot parse version requirement", Error) + return + let csourcesVersion = + #TODO We could test special against the special versionn-x branch to get the right csources + if nimVersion.isSpecial or (major == 1 and minor >= 9) or major >= 2: + # already uses csources_v2 + "csources_v2" + elif major == 0: + "csources" # has some chance of working + else: + "csources_v1" + cd workspace: + echo "Entering CSOURCES", csourcesVersion, " exists ", dirExists(csourcesVersion) + if not dirExists(csourcesVersion): + exec "git clone https://github.com/nim-lang/" & csourcesVersion + + cd workspace / csourcesVersion: + when defined(windows): + exec "build.bat" + else: + let makeExe = findExe("make") + if makeExe.len == 0: + exec "sh build.sh" + else: + exec "make" + let nimExe0 = ".." / csourcesVersion / "bin" / "nim".addFileExt(ExeExt) + cd nimDest: + let nimExe = "bin" / "nim".addFileExt(ExeExt) + copyFileWithPermissions nimExe0, nimExe + exec nimExe & " c --noNimblePath --skipUserCfg --skipParentCfg --hints:off koch" + let kochExe = when defined(windows): "koch.exe" else: "./koch" + exec kochExe & " boot -d:release --skipUserCfg --skipParentCfg --hints:off" + exec kochExe & " tools --skipUserCfg --skipParentCfg --hints:off" + # unless --keep is used delete the csources because it takes up about 2GB and + # is not necessary afterwards: + if not keepCsources: + removeDir workspace / csourcesVersion / "c_code" + let pathEntry = workspace / nimDest / "bin" + #remove nimble so it doesnt interfer with the current one: + removeFile "bin" / "nimble".addFileExt(ExeExt) + when defined(windows): + writeFile "activate.bat", BatchFile % pathEntry.replace('/', '\\') + else: + writeFile "activate.sh", ShellFile % pathEntry + infoAboutActivation nimDest, $nimVersion + + +proc useNimFromDir*(options: var Options, realDir: string, v: VersionRange, tryCompiling = false) = + const binaryName = when defined(windows): "nim.exe" else: "nim" + + let + nim = realDir / "bin" / binaryName + fileExists = fileExists(options.nimBin) + + if not fileExists(nim): + if tryCompiling and options.prompt("Develop version of nim was found but it is not compiled. Compile it now?"): + compileNim(options, realDir, v) + else: + raise nimbleError("Trying to use nim from $1 " % realDir, + "If you are using develop mode nim make sure to compile it.") + + options.nimBin = nim + let separator = when defined(windows): ";" else: ":" + + putEnv("PATH", realDir / "bin" & separator & getEnv("PATH")) + if fileExists: + display("Info:", "switching to $1 for compilation" % options.nim, priority = HighPriority) + else: + display("Info:", "using $1 for compilation" % options.nim, priority = HighPriority) diff --git a/src/nimblepkg/options.nim b/src/nimblepkg/options.nim index c4bf80b0..be410181 100644 --- a/src/nimblepkg/options.nim +++ b/src/nimblepkg/options.nim @@ -390,6 +390,11 @@ proc getPkgsLinksDir*(options: Options): string = proc getBinDir*(options: Options): string = options.getNimbleDir() / nimbleBinariesDirName +proc setPackageCache(options: var Options, baseDir: string) = + if options.useSatSolver: + options.pkgCachePath = baseDir / "pkgcache" + display("Info:", "Package cache path " & options.pkgCachePath, priority = HighPriority) + proc setNimbleDir*(options: var Options) = var nimbleDir = options.config.nimbleDir @@ -407,6 +412,7 @@ proc setNimbleDir*(options: var Options) = # --nimbleDir: