Include non-CRAN package in CRAN package
Asked Answered
D

3

19

The question is pretty simple. First:

  1. Is it possible to include a non-CRAN (or bioconductor, or omega hat) package in a CRAN package and actually use tools from that package in examples.
  2. If yes how does one set up the DESCRIPTION file etc. to make it legit and pass CRAN checks?

Specifically I'm asking about openNLPmodels.en that used to be a CRAN package. It's pretty useful and want to include functionality from it. I could do a work around and not actual use openNLPmodels.en in the examples or create unit tests for it, and have it install when a function gets use (similar to how the gender package installs the data sets it needs) but I'd prefer an approach that allows me to run checks, texts, examples.

This is how one downloads and installs openNLPmodels.en

install.packages(
    "http://datacube.wu.ac.at/src/contrib/openNLPmodels.en_1.5-1.tar.gz",  
    repos=NULL, 
    type="source"
)
Divulgence answered 25/10, 2015 at 21:32 Comment(3)
I'm not sure whether this is on-topic for Stack Overflow ... might be better for the r-packages-devel list (not sure exactly what it's called) ... ?Metopic
"Packages on which a CRAN package depends should be available from a mainstream repository: if any mentioned in ‘Suggests’ or ‘Enhances’ fields are not from such a repository, where to obtain them at a repository should be specified in an ‘Additional_repositories’ field of the DESCRIPTION file (as a comma-separated list of repository URLs) or for other means of access, described in the ‘Description’ field." cran.rstudio.org/web/packages/policies.htmlPalladino
That sounds like a bad idea. Why don't you copy over the functionality you need? It's open source? Or talk to the author of openNLPmodels.en and see if you can maybe adopt or fork it?Stockinet
D
1

Existing answer is good but doesn't explain the whole process fully in details so posting this one.


Is it possible to include a non-CRAN (or bioconductor, or omega hat) package in a CRAN package and actually use tools from that package in examples.

Yes, it is possible. Any use (package code, examples, tests, vignettes) of such non-CRAN has to be escaped as any other package in Suggests, ideally using

if (requireNamespace("non.cran.pkg", quietly=TRUE)) {
  non.cran.pkg::fun()
} else {
  cat("skipping functionality due to missing Suggested dependency")
}

If yes how does one set up the DESCRIPTION file etc. to make it legit and pass CRAN checks?

You need to use Additional_repositories field in DESCRIPTION file. Location provided in that field has to contain expect directory structure, PACKAGES file in appropriate directory, and PACKAGES file has to have non-CRAN package listed.


Now going to your particular example of openNLPmodels.en package. According to the way how you download and install this package it will not be possible to use it as dependency and pass on CRAN. openNLPmodels.en has to be published in a structure expected from R repository. Otherwise you don't have a valid location to put into Additional_repositories field.

What you can do is to download non-CRAN package and publish it in your R repository yourself, and then use that location in Additional_repositories field in your CRAN package. Here is an example of how to do it:

dir.create("src/contrib", recursive=TRUE)
download.file("http://datacube.wu.ac.at/src/contrib/openNLPmodels.en_1.5-1.tar.gz", "src/contrib/openNLPmodels.en_1.5-1.tar.gz")
tools::write_PACKAGES("src/contrib")

We just put package sources in expected directory src/contrib and the rest is nicely handled by write_PACKAGES function. To ensure that repository is properly created you can list packages that are available in that repository:

available.packages(repos=file.path("file:/",getwd()))

It should list your non-CRAN package there. Then having non-CRAN package published in R repository you should location of the repository into Additional_repositories field of your CRAN package. In this case location will be location returned by file.path("file:/",getwd()) expression.

Note that it uses location on your local machine, you will probably want to put it online, so that url can accessed by any machine checking your CRAN package, including checks on CRAN itself. For that just move your src directory to a public directory that is going to be hosted somewhere online and use the location of that server.


Now looking at your non-CRAN package again, we can see it has src/contrib in its url, thus we can assume that proper R repository already exists for it and we don't have to create and publish new one. Therefore your installation instruction could look like

install.packages(
  "openNLPmodels.en", 
  repos="http://datacube.wu.ac.at",
  type="source"
)

And then all you need for your CRAN package is to use existing repository where it is available

Additional_repositories http://datacube.wu.ac.at
Diphthong answered 20/11, 2020 at 10:9 Comment(0)
M
2

The usethis::use_dev_package function has solved this problem.

As an example, running this line:

usethis::use_dev_package(package = "h3", type = "Imports", remote = "crazycapivara/h3-r")

will automatically write the following lines to your DESCRIPTION file:

Imports: 
    h3 (>= 3.7.1)
Remotes:  
    crazycapivara/h3-r

Note that because github is the most commonly-used unofficial package distribution in R, it is the default. As such, make sure there is no github:: prefix to the entry in the Remotes section of the DESCRIPTION file.

Macrography answered 10/11, 2021 at 21:41 Comment(0)
D
1

Existing answer is good but doesn't explain the whole process fully in details so posting this one.


Is it possible to include a non-CRAN (or bioconductor, or omega hat) package in a CRAN package and actually use tools from that package in examples.

Yes, it is possible. Any use (package code, examples, tests, vignettes) of such non-CRAN has to be escaped as any other package in Suggests, ideally using

if (requireNamespace("non.cran.pkg", quietly=TRUE)) {
  non.cran.pkg::fun()
} else {
  cat("skipping functionality due to missing Suggested dependency")
}

If yes how does one set up the DESCRIPTION file etc. to make it legit and pass CRAN checks?

You need to use Additional_repositories field in DESCRIPTION file. Location provided in that field has to contain expect directory structure, PACKAGES file in appropriate directory, and PACKAGES file has to have non-CRAN package listed.


Now going to your particular example of openNLPmodels.en package. According to the way how you download and install this package it will not be possible to use it as dependency and pass on CRAN. openNLPmodels.en has to be published in a structure expected from R repository. Otherwise you don't have a valid location to put into Additional_repositories field.

What you can do is to download non-CRAN package and publish it in your R repository yourself, and then use that location in Additional_repositories field in your CRAN package. Here is an example of how to do it:

dir.create("src/contrib", recursive=TRUE)
download.file("http://datacube.wu.ac.at/src/contrib/openNLPmodels.en_1.5-1.tar.gz", "src/contrib/openNLPmodels.en_1.5-1.tar.gz")
tools::write_PACKAGES("src/contrib")

We just put package sources in expected directory src/contrib and the rest is nicely handled by write_PACKAGES function. To ensure that repository is properly created you can list packages that are available in that repository:

available.packages(repos=file.path("file:/",getwd()))

It should list your non-CRAN package there. Then having non-CRAN package published in R repository you should location of the repository into Additional_repositories field of your CRAN package. In this case location will be location returned by file.path("file:/",getwd()) expression.

Note that it uses location on your local machine, you will probably want to put it online, so that url can accessed by any machine checking your CRAN package, including checks on CRAN itself. For that just move your src directory to a public directory that is going to be hosted somewhere online and use the location of that server.


Now looking at your non-CRAN package again, we can see it has src/contrib in its url, thus we can assume that proper R repository already exists for it and we don't have to create and publish new one. Therefore your installation instruction could look like

install.packages(
  "openNLPmodels.en", 
  repos="http://datacube.wu.ac.at",
  type="source"
)

And then all you need for your CRAN package is to use existing repository where it is available

Additional_repositories http://datacube.wu.ac.at
Diphthong answered 20/11, 2020 at 10:9 Comment(0)
I
0

Its possible, but! ...

There is a field in the DESCRIPTION file that that you can use:

Additional_repositories: http://ghrr.github.io/drat

BUT!

Everything that depends on the functionality from the package from the additional repository has to be absolutely optional.

So packages from this repo should be placed under Suggests.

Example

I am not 100% sure whether or not BioConductor and OmegaHat are considered mainstream or not.

Interventionist answered 21/6, 2019 at 19:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.