From 49d8e23ad785e1b6aa203c3b3ac71fc18115854f Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Sat, 11 Feb 2023 19:22:44 +0200 Subject: [PATCH 1/6] Add testing workflow --- .github/workflows/check-standalone.yaml | 73 +++++++++++++++++++++++++ R/rstan_config.R | 46 +++++----------- 2 files changed, 87 insertions(+), 32 deletions(-) create mode 100644 .github/workflows/check-standalone.yaml diff --git a/.github/workflows/check-standalone.yaml b/.github/workflows/check-standalone.yaml new file mode 100644 index 0000000..7e7c25e --- /dev/null +++ b/.github/workflows/check-standalone.yaml @@ -0,0 +1,73 @@ +# Workflow derived from https://github.com/r-lib/actions/tree/master/examples +# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help +on: + push: + branches: [main, master] + pull_request: + branches: [main, master] + +name: Stanfunctions Support + +jobs: + stanfunctions-support: + runs-on: ${{ matrix.config.os }} + + name: ${{ matrix.config.os }} (${{ matrix.config.r }}) + + strategy: + fail-fast: false + matrix: + config: + - {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'} + - {os: ubuntu-latest, r: 'release'} + + env: + GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + R_KEEP_PKG_SOURCE: yes + + steps: + - uses: actions/checkout@v3 + + - uses: r-lib/actions/setup-pandoc@v2 + + - uses: r-lib/actions/setup-r@v2 + with: + r-version: ${{ matrix.config.r }} + http-user-agent: ${{ matrix.config.http-user-agent }} + use-public-rspm: true + + - uses: r-lib/actions/setup-r-dependencies@v2 + with: + extra-packages: local::. rcmdcheck BH RcppParallel RcppEigen Rcpp rstan StanHeaders + + - name: Checkout lgpr package + run: | + git clone https://github.com/andrjohns/lgpr + cd lgpr && git checkout function-exports + + - name: Check against CRAN StanHeaders and CRAN RStan + run: | + rcmdcheck::rcmdcheck(path = "lgpr", args = c("--no-manual", "--as-cran"), build_args = "--no-manual") + + - name: Install Development StanHeaders and CRAN RStan + run: | + Sys.setenv(MAKEFLAGS=paste0("-j",parallel::detectCores())) + install.packages("StanHeaders", repos = c("https://mc-stan.org/r-packages/", getOption("repos"))) + install.packages('rstan', type='source') + shell: Rscript {0} + + - name: Check against CRAN StanHeaders and CRAN RStan + run: | + rcmdcheck::rcmdcheck(path = "lgpr", args = c("--no-manual", "--as-cran"), build_args = "--no-manual") + + - name: Install Development StanHeaders and Development RStan + run: | + Sys.setenv(MAKEFLAGS=paste0("-j",parallel::detectCores())) + install.packages("StanHeaders", repos = c("https://mc-stan.org/r-packages/", getOption("repos"))) + install.packages("rstan", repos = c("https://mc-stan.org/r-packages/", getOption("repos"))) + shell: Rscript {0} + + - name: Check against CRAN StanHeaders and CRAN RStan + run: | + rcmdcheck::rcmdcheck(path = "lgpr", args = c("--no-manual", "--as-cran"), build_args = "--no-manual") + diff --git a/R/rstan_config.R b/R/rstan_config.R index bd69232..4721b0f 100644 --- a/R/rstan_config.R +++ b/R/rstan_config.R @@ -179,9 +179,9 @@ rstan_config <- function(pkgdir = ".") { if (grepl("\\.stanfunctions$", file_name) && (utils::packageVersion('rstan') < 2.29)) { mod <- readLines(file_name) - file_name <- paste0(.basename_noext(file_name), "_wrapped.stanfunctions") - cat("functions {", mod, "}", sep = "\n", - file = file_name) + if (!any(grepl("\\bfunctions \\{", mod))) { + cat("functions {", mod, "}", sep = "\n", file = file_name) + } } stanc_ret <- rstan::stanc(file_name, allow_undefined = TRUE, obfuscate_model_name = FALSE, @@ -215,7 +215,7 @@ rstan_config <- function(pkgdir = ".") { } cat("#include ", "#include ", - "#include ", + "#include ", file = file.path(pkgdir, "src", paste(basename(pkgdir), "types.h", sep = "_")), sep = "\n") @@ -351,41 +351,23 @@ rstan_config <- function(pkgdir = ".") { # Replace auto return type in function exports with the plain type from the main body. .replace_auto <- function(decl_line, cppcode, cpp_lines) { # Extract the name of function - decl <- cpp_lines[decl_line] - decl <- gsub("auto ","",decl,fixed=T) - decl <- sub("\\(.*","",decl,perl=T) - - # Replace newlines with blank spaces - t3 <- gsub("\n"," ",cppcode,fixed=T) - - # Identify code segment containing first declaration of function - sf1 <- strsplit(t3,decl,fixed=T)[[1]][1] - sf2 <- utils::tail(strsplit(sf1,";",fixed=T)[[1]],1) - - # Get location of type promotion (if present) - promote_start <- regexec("stan::promote_args_t<",sf2)[[1]] + fun_name <- cpp_lines[decl_line] + fun_name <- gsub("auto ","",fun_name,fixed=T) + fun_name <- sub("\\(.*","",fun_name,perl=T) - if(promote_start > 0) { + struct_start <- grep(paste0("struct ", fun_name, "_functor"), cpp_lines) + struct_op_start <- grep("operator()", cpp_lines[-(1:struct_start)])[1] + struct_start - str_t <- strsplit(sf2,"")[[1]] - promote_end <- promote_start + attr(promote_start,'match.length') + rtn_type <- paste0(cpp_lines[struct_start:struct_op_start], collapse = " ") - count <- 1 + rm_operator <- gsub("operator().*", "", rtn_type) + rm_struct_decl <- gsub(".*\\{", "", rm_operator) + repl_dbl <- gsub("T([0-9])*__", "double", rm_struct_decl) - while(count > 0 & promote_end < length(str_t)) { - count <- count + ifelse(str_t[promote_end] == "<", 1, - ifelse(str_t[promote_end] == ">", -1,0)) - promote_end <- promote_end + 1 - } - - sf2 <- paste0(c(str_t[1:(promote_start-1)], "double", - str_t[promote_end:length(str_t)]), - collapse = "") - } # Extract return type declaration and replace promoted scalar # type with double - rtn_type <- gsub("template ","",sf2) + rtn_type <- gsub("template ", "", repl_dbl) # Update model code with type declarations gsub("auto ", rtn_type, cpp_lines[decl_line],fixed=T) From abeb709a7591d9ca1c5c18c7a6df7ff097d860e8 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Sat, 11 Feb 2023 19:28:50 +0200 Subject: [PATCH 2/6] Update actions --- .github/workflows/check-standalone.yaml | 3 +++ .github/workflows/check-standard.yaml | 16 ++++++++-------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/.github/workflows/check-standalone.yaml b/.github/workflows/check-standalone.yaml index 7e7c25e..b23b95a 100644 --- a/.github/workflows/check-standalone.yaml +++ b/.github/workflows/check-standalone.yaml @@ -48,6 +48,7 @@ jobs: - name: Check against CRAN StanHeaders and CRAN RStan run: | rcmdcheck::rcmdcheck(path = "lgpr", args = c("--no-manual", "--as-cran"), build_args = "--no-manual") + shell: Rscript {0} - name: Install Development StanHeaders and CRAN RStan run: | @@ -59,6 +60,7 @@ jobs: - name: Check against CRAN StanHeaders and CRAN RStan run: | rcmdcheck::rcmdcheck(path = "lgpr", args = c("--no-manual", "--as-cran"), build_args = "--no-manual") + shell: Rscript {0} - name: Install Development StanHeaders and Development RStan run: | @@ -70,4 +72,5 @@ jobs: - name: Check against CRAN StanHeaders and CRAN RStan run: | rcmdcheck::rcmdcheck(path = "lgpr", args = c("--no-manual", "--as-cran"), build_args = "--no-manual") + shell: Rscript {0} diff --git a/.github/workflows/check-standard.yaml b/.github/workflows/check-standard.yaml index c97ec37..7f9bfee 100644 --- a/.github/workflows/check-standard.yaml +++ b/.github/workflows/check-standard.yaml @@ -20,7 +20,7 @@ jobs: config: - {os: macOS-latest, r: 'release'} # Vignette building hangs infinitely on Windows GHA, so disable for now - #- {os: windows-latest, r: 'release'} + - {os: windows-latest, r: 'release'} - {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'} - {os: ubuntu-latest, r: 'release'} - {os: ubuntu-latest, r: 'oldrel-1'} @@ -30,22 +30,22 @@ jobs: R_KEEP_PKG_SOURCE: yes steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - - uses: r-lib/actions/setup-pandoc@v1 + - uses: r-lib/actions/setup-pandoc@v2 - - uses: r-lib/actions/setup-r@v1 + - uses: r-lib/actions/setup-r@v2 with: r-version: ${{ matrix.config.r }} http-user-agent: ${{ matrix.config.http-user-agent }} use-public-rspm: true - - uses: r-lib/actions/setup-r-dependencies@v1 + - uses: r-lib/actions/setup-r-dependencies@v2 with: extra-packages: rcmdcheck BH RcppParallel RcppEigen Rcpp rstan StanHeaders - name: Check against CRAN StanHeaders and CRAN RStan - uses: r-lib/actions/check-r-package@v1 + uses: r-lib/actions/check-r-package@v2 - name: Install Development StanHeaders and CRAN RStan run: | @@ -55,7 +55,7 @@ jobs: shell: Rscript {0} - name: Check against Development StanHeaders and CRAN RStan - uses: r-lib/actions/check-r-package@v1 + uses: r-lib/actions/check-r-package@v2 - name: Install Development StanHeaders and Development RStan run: | @@ -65,7 +65,7 @@ jobs: shell: Rscript {0} - name: Check against Development StanHeaders and Development RStan - uses: r-lib/actions/check-r-package@v1 + uses: r-lib/actions/check-r-package@v2 - name: Show testthat output if: always() From 888dcafa0ccaf1083d0072be8a5e7bfe982d4bf2 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Sat, 11 Feb 2023 19:33:48 +0200 Subject: [PATCH 3/6] lgpr deps --- .github/workflows/check-standalone.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/check-standalone.yaml b/.github/workflows/check-standalone.yaml index b23b95a..8847acd 100644 --- a/.github/workflows/check-standalone.yaml +++ b/.github/workflows/check-standalone.yaml @@ -38,7 +38,7 @@ jobs: - uses: r-lib/actions/setup-r-dependencies@v2 with: - extra-packages: local::. rcmdcheck BH RcppParallel RcppEigen Rcpp rstan StanHeaders + extra-packages: local::. rcmdcheck BH RcppParallel RcppEigen Rcpp rstan StanHeaders RCurl - name: Checkout lgpr package run: | From 26f2c2b1e8e1833225ccb73ff3a409b86ceda233 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Sat, 11 Feb 2023 20:16:20 +0200 Subject: [PATCH 4/6] Update action versions --- .github/workflows/check-standalone.yaml | 4 ++-- .github/workflows/check-standard.yaml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/check-standalone.yaml b/.github/workflows/check-standalone.yaml index 8847acd..69c85b4 100644 --- a/.github/workflows/check-standalone.yaml +++ b/.github/workflows/check-standalone.yaml @@ -57,7 +57,7 @@ jobs: install.packages('rstan', type='source') shell: Rscript {0} - - name: Check against CRAN StanHeaders and CRAN RStan + - name: Check against Development StanHeaders and CRAN RStan run: | rcmdcheck::rcmdcheck(path = "lgpr", args = c("--no-manual", "--as-cran"), build_args = "--no-manual") shell: Rscript {0} @@ -69,7 +69,7 @@ jobs: install.packages("rstan", repos = c("https://mc-stan.org/r-packages/", getOption("repos"))) shell: Rscript {0} - - name: Check against CRAN StanHeaders and CRAN RStan + - name: Check against Development StanHeaders and Development RStan run: | rcmdcheck::rcmdcheck(path = "lgpr", args = c("--no-manual", "--as-cran"), build_args = "--no-manual") shell: Rscript {0} diff --git a/.github/workflows/check-standard.yaml b/.github/workflows/check-standard.yaml index 7f9bfee..680dc7b 100644 --- a/.github/workflows/check-standard.yaml +++ b/.github/workflows/check-standard.yaml @@ -20,7 +20,7 @@ jobs: config: - {os: macOS-latest, r: 'release'} # Vignette building hangs infinitely on Windows GHA, so disable for now - - {os: windows-latest, r: 'release'} + #- {os: windows-latest, r: 'release'} - {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'} - {os: ubuntu-latest, r: 'release'} - {os: ubuntu-latest, r: 'oldrel-1'} From 498536ca56785c61451b1e38a0fc2131560d4d00 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Fri, 3 Mar 2023 11:06:52 +0800 Subject: [PATCH 5/6] Use writeLines, flexible regex for spaces --- R/rstan_config.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/R/rstan_config.R b/R/rstan_config.R index 4721b0f..66b4925 100644 --- a/R/rstan_config.R +++ b/R/rstan_config.R @@ -179,8 +179,8 @@ rstan_config <- function(pkgdir = ".") { if (grepl("\\.stanfunctions$", file_name) && (utils::packageVersion('rstan') < 2.29)) { mod <- readLines(file_name) - if (!any(grepl("\\bfunctions \\{", mod))) { - cat("functions {", mod, "}", sep = "\n", file = file_name) + if (!any(grepl("\\bfunctions(\\s*|)\\{", mod))) { + writeLines("functions {", mod, "}", sep = "\n", con = file_name) } } stanc_ret <- rstan::stanc(file_name, allow_undefined = TRUE, From 1b11131d5e90da589e9f54efd63e3a50d86db6f4 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Fri, 3 Mar 2023 11:35:45 +0800 Subject: [PATCH 6/6] writeLines handling --- R/rstan_config.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/rstan_config.R b/R/rstan_config.R index 66b4925..5de4817 100644 --- a/R/rstan_config.R +++ b/R/rstan_config.R @@ -180,7 +180,7 @@ rstan_config <- function(pkgdir = ".") { (utils::packageVersion('rstan') < 2.29)) { mod <- readLines(file_name) if (!any(grepl("\\bfunctions(\\s*|)\\{", mod))) { - writeLines("functions {", mod, "}", sep = "\n", con = file_name) + writeLines(c("functions {", mod, "}"), sep = "\n", con = file_name) } } stanc_ret <- rstan::stanc(file_name, allow_undefined = TRUE,