r-lib / pkgload

Simulate installing and loading a package
http://pkgload.r-lib.org
58 stars 46 forks source link

Generate compilation database on load #285

Closed lionel- closed 3 months ago

lionel- commented 3 months ago

LSPs like clangd provide intellisense features for native files but they need to know the build flags (mostly include flags) for each root file in the project (flags for included files are inferred from root files). These tools are not able to infer the flags by themselves and so require the generation of a "compilation database": https://clang.llvm.org/docs/JSONCompilationDatabase.html.

For R packages the flags are generated by R CMD build and depend on the package Makevars file, possibly generated from configure. Generating the database after a load_all() seems like a reasonable update point to keep track of the changing source files (which can be added or removed during development) while ensuring the presence of an up-to-date Makevars file.

There are two main approaches for the generation of a compilation database. The first is to intercept the compiler calls during an actual build to collect arguments. This is the approach used by tools like bear and it works great in conjunction with R CMD build. The other is to generate build commands, e.g. with make --dry-run.

@kevinushey suggested we could use the latter approach with R CMD shlib --dry-run. This is a nice idea because it means we don't need any external tools to create the database. This PR implements this approach. A few caveats:

The compilation database is not generated by default, the user must explicitly opt in by inserting this line in their DESCRIPTION file:

Config/devtools/compilation-database: true

In addition the compile_commands.json file generated at the root should be gitignored and Rbuildignored. We'll provide a usethis function to accomplish these tasks.

The tools for generating this database should probably be moved and reexported from pkgbuild in the future (cc @gaborcsardi), but I'm implementing them here as I'd like to include the feature in the next release of pkgload.

Untested on Windows but should work on Unixes. Tested on macOS with readxl, rlang, igraph, and r-tree-sitter. Edit: now working on Windows

lionel- commented 3 months ago

I've added a currently unexported util to help set this up: pkgload:::use_compilation_db()