Make R SDK CRAN-conformant via vendored source build#179
Merged
Conversation
Refactor the R package to compile the JSON Structure C engine from vendored sources at install time instead of downloading a prebuilt shared library at runtime. CRAN forbids install/runtime network access, so the download model could never be accepted; this makes the package self-contained and installable from source on every platform. Engine sourcing - Vendor the engine translation units (error_codes.c, instance_validator.c, json_source_locator.c, schema_validator.c, types.c), the public headers under src/json_structure/, and cJSON v1.7.18 (MIT, (c) Dave Gamble) into r/src/. cJSON attribution is recorded in inst/COPYRIGHTS. - Add tools/vendor-engine.R to re-sync the engine sources/headers from c/ into r/src/ (kept out of the build tarball via .Rbuildignore). - Remove the runtime binary installer (R/binary_installer.R and its docs); drop the download/dlopen path from ffi.R/zzz.R. Windows std::regex deadlock -> pure-C matcher - MinGW libstdc++ std::regex deadlocks on first use whenever its DLL is loaded by R on Windows (lazy locale init via __gthread_once under the fully-static Rtools toolchain). This is unfixable by link flags, so the vendored regex_utils.cpp is replaced with regex_utils.c, a self-contained ECMAScript-subset backtracking matcher (pure C, no threads/TLS, ReDoS step budget). The package is now pure C: no libstdc++ dependency. - The upstream C SDK (c/src/regex_utils.cpp) is unchanged; only the R vendored copy differs. regex_utils.h documents the split. C engine (shared source of truth) - Replace three bounded snprintf copies in instance_validator.c and schema_validator.c with memcpy to silence -Wformat-truncation so the vendored build is warning-free after any re-sync. C SDK tests unaffected. Build, CI, docs - Makevars: Unix keeps $(SHLIB_PTHREAD_FLAGS) for the engine allocator lock; Makevars.win links nothing extra (SRWLOCK from kernel32). No C++/libstdc++. - .github/workflows/r.yml: single source-build matrix over ubuntu/macos/windows, R CMD check with --as-cran and error-on warning, corpus exercised via JSONSTRUCTURE_TEST_ASSETS; drop the separate C-build and Windows jobs. - Update README/NEWS/cran-comments and regenerate man/ for the pure-C, source-build model. R CMD check --as-cran: 0 errors, 0 warnings, 2 notes (new submission; cJSON pragma), with the shared test-assets corpus passing during the check. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The CRAN "checking compiled code" check flags `__sprintf_chk` (from `sprintf`) on Linux/macOS as a disallowed entry point, producing a WARNING that fails `R CMD check --as-cran` under error-on=warning. (MinGW on Windows does not emit the fortified symbol, so the local Windows check did not surface it.) Replace all `sprintf()` calls in the vendored `src/cJSON.c` with bounded `snprintf()` (using the target buffer sizes). Behavior is unchanged since the buffers were already adequately sized; the package's testthat corpus still passes. Disclose the modification in cran-comments.md, inst/COPYRIGHTS, the cJSON.c header, and NEWS.md, and correct the COPYRIGHTS engine file list to reference regex_utils.c (pure C) rather than the upstream regex_utils.cpp. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Make the R SDK CRAN-conformant (vendored source build)
Why
The R package previously downloaded a prebuilt
libjson_structuresharedlibrary from GitHub Releases at install / first load. CRAN forbids
install-time and runtime network access, so that model could never pass
R CMD check --as-cranand the package could not be published. This PRrefactors the package to be self-contained and built from source on every
platform.
What changed
Vendored source build (no runtime download)
under
r/src/json_structure/, and cJSON v1.7.18 (MIT, © Dave Gamble)into
r/src/. The package now compiles the engine at install time.r/inst/COPYRIGHTS.r/tools/vendor-engine.Rre-syncs the engine.c/headers fromc/into
r/src/(excluded from the tarball via.Rbuildignore).R/binary_installer.R+ its docs) andthe download/
dlopenpath inffi.R/zzz.R.Windows
std::regexdeadlock → pure-C matcherMinGW libstdc++
std::regexdeadlocks on first use whenever its DLL isloaded by R on Windows (lazy locale init via
__gthread_onceunder thefully-static Rtools toolchain). It is unfixable by link flags, static/shared
runtime selection, or thread warmups — and CRAN mandates that exact static
toolchain.
regex_utils.cppwithregex_utils.c, aself-contained ECMAScript-subset backtracking matcher: pure C, no
threads/TLS, char-class bitmaps, greedy/lazy quantifiers, anchors, word
boundaries, escapes, groups, alternation. Invalid/unsupported constructs
(lookbehind, named groups, inline flags,
\p{…}, lookahead) are rejectedas invalid, matching
std::regex's throw-on-parse behavior. ReDoS isbounded by a step budget.
c/src/regex_utils.cpp) is unchanged; only the Rvendored copy differs.
regex_utils.hdocuments the split.C engine (shared source of truth)
snprintfcopies inc/src/instance_validator.candc/src/schema_validator.cwithmemcpyto silence-Wformat-truncation,so the vendored build stays warning-free after any re-sync. C SDK tests
unaffected (all pass).
Build / CI / docs
Makevars: Unix keeps$(SHLIB_PTHREAD_FLAGS)for the engine's allocatorlock;
Makevars.winlinks nothing extra (SRWLOCK from kernel32). No C++..github/workflows/r.yml: a single source-build matrix overubuntu / macos / windows;
R CMD checkwith--as-cranand error-onwarning; the shared corpus is exercised via
JSONSTRUCTURE_TEST_ASSETS.The separate C-build and Windows jobs are removed.
man/regenerated for thepure-C, source-build model.
Validation
R CMD check --as-cran --no-manualon a fresh tarball:0 errors, 0 warnings, 2 notes (both expected and documented in
cran-comments.md). The sharedtest-assets/corpus runs during the check:[ FAIL 0 | WARN 0 | SKIP 1 | PASS 74 ](the single skip is the optionalprimer-samples directory, not shipped in the tarball). Verified as a pure-C
build (all
gcc, nog++/libstdc++) and with no Windows regex hang.Notes
conformant so a future submission (or r-universe) is possible.