R/makify.R

Defines functions makify

#' Internal: Construct a Makefile
#'
#' This function constructs a \code{Makefile} object for a package web.
#' Call the exported \code{\link{write_makefile}} function to
#' write a \code{Makefile} to the web's root directory.
#'
#' @param web The web to construct the \code{Makefile} for
#' @param target_dir Target directory for \code{Makefile}, default: the web's root
#'   directory
#' @param lib_dir Library directory for installation, default: User library
#' @return A Makefile
#'
#' @importFrom MakefileR make_rule make_def make_group make_comment make_text
makify <- function(web = rpkgweb(), target_dir = NULL, lib_dir = NULL) {
  web <- as.rpkgweb(web)

  target_dir <- get_target_dir(web, target_dir)

  target_dir_rel <- R.utils::getRelativePath(target_dir, root_dir(web))
  if (grepl("^[.][.]", target_dir_rel)) {
    stop("target_dir must reside inside the web.", call. = FALSE)
  }

  root_dir_rel <- R.utils::getRelativePath(root_dir(web), target_dir)

  if (is.null(lib_dir)) {
    lib_dir <- .libPaths()[[1L]]
    lib_dir_arg <- "NULL"
    lib_export <- FALSE
  } else {
    lib_dir <- normalize_path(lib_dir)
    lib_dir_arg <- sprintf("'%s'", lib_dir)
    lib_export <- TRUE
  }

  # Local definitions
  r <- function(..., data = parent.frame()) {
    expr <- paste(..., sep = "; ")
    expr <- whisker::whisker.render(expr, data = data)
    sprintf("Rscript -e \"tryCatch({%s}, error = function(e) { message(e$$message, '\\n'); quit('no', 10) })\"", expr)
  }

  check_dir <- "rpkgweb-check"
  check_log_path <- . %>% sprintf("%s.Rcheck", .) %>% file.path(check_dir, ., "00check.log")
  code_desc_path <- . %>% file.path(root_dir_rel, ., "DESCRIPTION")
  code_desc_path_x <- . %>% sprintf("$(patsubst(%%,${RPKGWEB_ROOT_DIR}/%%/DESCRIPTION,%s))", .)

  rpkgweb_qualify <- Sys.getenv("RPKGWEB_QUALIFY", "rpkgweb::")

  pkg_name <- "$(notdir $(patsubst %/,%,$(dir $<)))"

  check_dir_create_call <-
    "dir.create('{{{ check_dir }}}', showWarnings = FALSE, recursive = TRUE)"

  run_check_call <-
    "devtools::check('{{{ pkg_name }}}', cleanup = FALSE, check_dir = '{{{ check_dir }}}')"
  # End local definitions

  g <- make_group(make_comment("Autogenerated using rpkgweb"), sep = "")

  if (Sys.getenv("RPKGWEB_QUALIFY") != "")
    g <- g +
      make_group(
        make_comment("Use alternative loading method for rpkgweb library"),
        make_def("RPKGWEB_QUALIFY", Sys.getenv("RPKGWEB_QUALIFY")),
        make_text("export RPKGWEB_QUALIFY")
      )

  g +
    make_group(
      make_comment("Web"),
      make_def("RPKGWEB_ROOT_DIR", root_dir_rel)
    ) +
    make_group(
      make_comment("Package library"),
      make_def("RPKGWEB_LIB", lib_dir),
      make_def("RPKGWEB_LIB_ARG", lib_dir_arg)
    ) +
    (
      if (lib_export) {
        make_group(
          make_comment("prepend to R_LIBS"),
          make_text(sprintf("R_LIBS::=%s:${R_LIBS}", lib_dir)),
          make_text("export R_LIBS")
        )
      } else {
        make_comment("don't re-export R_LIBS")
      }
    ) +
    make_group(
      make_comment("All packages"),
      make_def("RPKGWEB_PACKAGES", web %>% names %>% paste(collapse = " "))
    ) +
    make_group(
      make_comment("Universal targets"),
      make_rule("all", "all-install"),
      make_rule("all-install", "${RPKGWEB_PACKAGES}"),
      make_rule("all-check", "$(RPKGWEB_PACKAGES:%=check-%)")
    ) +
    make_group(
      make_comment("Dummy file rules for interaction with other Makefiles"),
      make_rule(".rpkgweb-all-install", "all-install", "touch -r ${RPKGWEB_LIB} $@")
    ) +
    make_rule(".FORCE") +
    make_rule(
      "Makefile", c("${RPKGWEB_ROOT_DIR}", "${RPKGWEB_PACKAGES}" %>% code_desc_path_x),
      r("{{{ rpkgweb_qualify }}}write_makefile(web = '${RPKGWEB_ROOT_DIR}', target_dir='.', lib_dir=${RPKGWEB_LIB_ARG})")) +
    make_rule(
      "info", ".FORCE",
      r("{{{ rpkgweb_qualify }}}rpkgweb('${RPKGWEB_ROOT_DIR}')")) +
    make_rule(
      lib_desc_path("%"), code_desc_path("%"),
      r("{{{ rpkgweb_qualify }}}check_up('{{{ pkg_name }}}', web = '${RPKGWEB_ROOT_DIR}')")) +
    make_rule(
      check_log_path("%"), c(code_desc_path("%"), lib_desc_path("%")),
      r(paste(check_dir_create_call, run_check_call, sep = "; "))) +
    (
      web %>%
        names %>%
        lapply(. %>% { make_rule(., lib_desc_path(.)) } ) %>%
        make_group(make_comment("Convenience targets"), .dots = .)
    ) +
    (
      web %>%
        names %>%
        lapply(. %>% { make_rule(sprintf("check-%s", .), check_log_path(.)) } ) %>%
        make_group(make_comment("Convenience targets for checking"), .dots = .)
    ) +
    makify_deps(web %>% deps_df)
}

#' @importFrom MakefileR make_rule
makify_deps <- function(y) {
  y <- y %>% subset(internal)
  rules <- mapply(y$package %>% lib_desc_path,
                  y$dep_package %>% lib_desc_path,
                  FUN = make_rule, SIMPLIFY = FALSE)
  Reduce(c, rules, init = make_group(make_comment("Dependencies")))
}

lib_desc_path <- . %>% file.path("${RPKGWEB_LIB}", ., "DESCRIPTION")
krlmlr/rpkgweb documentation built on May 20, 2019, 6:18 p.m.