Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions .github/workflows/R-CMD-check-wsl.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,6 @@ jobs:
CMDSTANR_OPENCL_TESTS: true

steps:
- name: cmdstan env vars
run: |
echo "CMDSTAN_PATH=${HOME}/.cmdstan" >> $GITHUB_ENV
shell: bash

- uses: actions/checkout@v6

- uses: r-lib/actions/setup-r@v2
Expand All @@ -44,7 +39,7 @@ jobs:
with:
extra-packages: any::rcmdcheck, local::.

- uses: Vampire/setup-wsl@v6
- uses: Vampire/setup-wsl@v7
with:
distribution: Ubuntu-22.04
wsl-version: 2
Expand All @@ -55,12 +50,18 @@ jobs:
run: |
sudo apt-get update
sudo apt-get install -y build-essential libopenmpi-dev ocl-icd-opencl-dev pocl-opencl-icd
sudo chmod 755 /root
shell: wsl-bash {0}

- name: Install cmdstan
run: |
cmdstanr::check_cmdstan_toolchain()
cmdstanr::install_cmdstan(cores = 2, wsl = TRUE, overwrite = TRUE)
cat(
paste0("CMDSTAN=", cmdstanr::cmdstan_path(), "\n"),
file = Sys.getenv("GITHUB_ENV"),
append = TRUE
)
shell: Rscript {0}

- name: Session info
Expand Down
44 changes: 40 additions & 4 deletions R/path.R
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
#' @export
#'
#' @param path (string) The full file path to the CmdStan installation. If
#' `NULL` (the default) then the path is set to the default path used by
#' `NULL` (the default) then the path is set using the `"CMDSTAN"`
#' environment variable when available, otherwise the default path used by
#' [install_cmdstan()] if it exists.
#' @return A string. Either the file path to the CmdStan installation or the
#' CmdStan version number.
Expand Down Expand Up @@ -39,7 +40,8 @@
#'
set_cmdstan_path <- function(path = NULL) {
if (is.null(path)) {
path <- cmdstan_default_path()
env_path <- Sys.getenv("CMDSTAN")
path <- if (nzchar(env_path)) env_path else cmdstan_default_path()
}
if (dir.exists(path)) {
path <- absolute_path(path)
Expand Down Expand Up @@ -219,22 +221,56 @@ cmdstan_default_path <- function(dir = NULL) {
latest_cmdstan
}

is_wsl_unc_path <- function(path) {
is.character(path) &&
length(path) == 1 &&
!is.na(path) &&
startsWith(repair_path(path), "//wsl$/")
}

cmdstan_version_from_path <- function(path) {
path <- repair_path(path)
match <- regmatches(
path,
regexpr("cmdstan-[0-9]+\\.[0-9]+\\.[0-9]+(?:-rc[0-9]+)?$", path)
)
if (!length(match) || is.na(match) || !nzchar(match)) {
return(NULL)
}
sub("^cmdstan-", "", match)
}


#' Find the version of CmdStan from makefile
#' @noRd
#' @param path Path to installation.
#' @return Version number as a string.
read_cmdstan_version <- function(path) {
makefile_path <- file.path(path, "makefile")
if (!file.exists(makefile_path)) {
if (is_wsl_unc_path(path)) {
makefile <- tryCatch(
suppressWarnings(readLines(makefile_path, warn = FALSE)),
error = function(e) NULL
)
} else if (file.exists(makefile_path)) {
makefile <- readLines(makefile_path)
} else {
makefile <- NULL
}
if (is.null(makefile)) {
if (is_wsl_unc_path(path)) {
version_from_path <- cmdstan_version_from_path(path)
if (!is.null(version_from_path)) {
return(version_from_path)
}
}
warning(
"Can't find CmdStan makefile to detect version number. ",
"Path may not point to valid installation.",
call. = FALSE
)
return(NULL)
}
makefile <- readLines(makefile_path)
version_line <- grep("^CMDSTAN_VERSION :=", makefile, value = TRUE)
if (length(version_line) == 0) {
stop("CmdStan makefile is missing a version number.", call. = FALSE)
Expand Down
3 changes: 2 additions & 1 deletion man/set_cmdstan_path.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion tests/testthat/test-install.R
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ test_that("install_cmdstan() works with version and release_url", {
fixed = TRUE
)
expect_true(dir.exists(file.path(dir, "cmdstan-2.36.0")))
set_cmdstan_path(cmdstan_default_path())
set_cmdstan_path()
})

test_that("toolchain checks on Unix work", {
Expand All @@ -143,6 +143,7 @@ test_that("toolchain checks on Unix work", {
})

test_that("clean and rebuild works", {
set_cmdstan_path()
expect_output(
rebuild_cmdstan(cores = CORES),
paste0("CmdStan v", cmdstan_version(), " built"),
Expand Down
21 changes: 21 additions & 0 deletions tests/testthat/test-path.R
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,17 @@ test_that("Setting path from env var is detected", {
expect_false(is.null(.cmdstanr$VERSION))
})

test_that("set_cmdstan_path() uses CMDSTAN env var when path is omitted", {
unset_cmdstan_path()
withr::local_envvar(c(CMDSTAN = PATH))
expect_message(
set_cmdstan_path(),
paste("CmdStan path set to:", PATH),
fixed = TRUE
)
expect_equal(cmdstan_path(), PATH)
})

test_that("Unsupported CmdStan path from env var is rejected", {
unset_cmdstan_path()
.cmdstanr$WSL <- TRUE
Expand Down Expand Up @@ -184,6 +195,16 @@ test_that("CmdStan version helpers handle invalid inputs", {
expect_false(is_supported_cmdstan_version("not-a-version"))
})

test_that("CmdStan version can be recovered from WSL UNC install path", {
wsl_path <- "//wsl$/Ubuntu-22.04/root/.cmdstan/cmdstan-2.38.0"

expect_true(is_wsl_unc_path(wsl_path))
expect_equal(cmdstan_version_from_path(wsl_path), "2.38.0")
expect_equal(cmdstan_version_from_path(paste0(wsl_path, "/")), "2.38.0")
expect_equal(suppressWarnings(read_cmdstan_version(wsl_path)), "2.38.0")
expect_null(cmdstan_version_from_path("//wsl$/Ubuntu-22.04/root/.cmdstan/not-cmdstan"))
})

test_that("cmdstan_ext() works", {
if (os_is_windows() && !os_is_wsl()) {
expect_identical(cmdstan_ext(), ".exe")
Expand Down
Loading