Frequently Asked Questions (FAQs) by First-Time Contributors to stdlib.
- Introduction
- As a first-time contributor to stdlib, where should I start?
- How can I set up my development environment to contribute to stdlib?
- How can I install cppcheck?
- I am seeing different return values in the JavaScript and C implementation for the same implementation.
- What should I do if linting on my commits fails because my headings or lines exceed the maximum permissible length?
- What should I do if JavaScript linting on my commits fails because my function exceeds the maximum permissible number of parameters?
- I have opened a pull request, where can I seek feedback?
- I need to generate fixtures for my tests. How can I do that, and what are the best references for inspiration?
- How can I generate the test coverage report for a specific package locally?
- I am facing a
Uninitialized variable
linting error in my C files, how can I fix it? - I have the required packages in the expected paths, but I am still encountering an error like this while compiling the native add-on.
- When should I use decimals in examples, benchmarks, and documentation, and when should I avoid them?
- How should I name my pull request?
- How do I call the stdlib bot on my PR?
- Why were many unrelated files automatically pushed to my PR when I committed my changes?
- Frequently used
make
commands - Other Links
We appreciate your interest in contributing to stdlib! Below, we've compiled answers to some frequently asked questions (FAQs) from first-time contributors. If you're new to the project or encounter any challenges, this guide is a great place to start.
We recommend first familiarizing yourself with the stdlib codebase by reading the contributing and development guides. Once comfortable, you can start by working on a good first issue, fixing a bug, or resolving a TODO in the source code.
There are primarily two options for setting up your development environment to contribute to stdlib:
Note: The dev container does not yet support ARM64 architectures. For more information, or if you're interested in adding ARM64 support, you can visit this issue.
We use cppcheck
in our project to perform linting on C/C++ code. To install cppcheck
according to our project conventions, follow the specified installation step.
$ make deps-install-cppcheck
For more installation commands, visit this link.
I am seeing different return values in the JavaScript and C implementation for the same implementation.
First, verify that your implementation is truly the same and does not contain any bugs. Second, check whether your compiler is performing optimizations that may affect accuracy. A common optimization is rearranging terms. To check this, compile the add-on while disabling the optimization:
CFLAGS="-ffp-contract=off" make install-node-addons NODE_ADDONS_PATTERN="math/base/special/foo"
Then, run the tests:
make test TESTS_FILTER=".*/math/base/special/foo/.*"
If they pass, adjust the tolerance and add a note to the C tests indicating that the tolerance is higher compared to the JavaScript implementation due to compiler optimizations. If they fail, raise an issue with the maintainers to get feedback.
What should I do if linting on my commits fails because my headings or lines exceed the maximum permissible length?
Consider whether the heading/line can be shortened by renaming variables (e.g., changing strideX
to sx
). If shortening is not possible, disable the lint rule at the top level using:
- For JavaScript files:
// eslint-disable-line max-len
- For Markdown files:
<!-- lint disable maximum-heading-length -->
What should I do if JavaScript linting on my commits fails because my function exceeds the maximum permissible number of parameters?
Consider whether the number of parameters can be reduced. If reduction is not possible, disable the lint rule at the top level using:
// eslint-disable-line max-params
Consider joining our Gitter channel! We are proud to have a very active community where members help each other by asking and answering questions. A maintainer will review your pull request soon and provide feedback. You can also discuss it during our weekly office hours meeting!
I need to generate fixtures for my tests. How can I do that, and what are the best references for inspiration?
Tests are a crucial part of any standard library package. We take our goal of achieving 100% test coverage very seriously and expect your work to be backed by tests. Often, you may need to generate fixtures to validate your implementation against an existing reliable source. You can use Julia, R, Python, or other languages to generate fixtures. To see how we do this, refer to these example scripts: Python fixture script, Julia fixture script.
To generate the test coverage report for a specific package, you can use the following commands:
$ make test-cov TESTS_FILTER=".*/math/base/special/floorn/.*"
$ make view-cov
Modify the TESTS_FILTER
argument to specify the package you want to test. The view-cov
command will open the coverage report in your default web browser.
lib/node_modules/@stdlib/stats/base/dmeanvarpn/benchmark/c/benchmark.length.c:112:38: warning: Uninitialized variable: x [uninitvar]
stdlib_strided_dmeanvarpn( len, 1, x, 1, out, 1 );
^
lib/node_modules/@stdlib/stats/base/dmeanvarpn/benchmark/c/benchmark.length.c:104:17: note: Assuming condition is false
for ( i = 0; i < len; i++ ) {
^
lib/node_modules/@stdlib/stats/base/dmeanvarpn/benchmark/c/benchmark.length.c:112:38: note: Uninitialized variable: x
stdlib_strided_dmeanvarpn( len, 1, x, 1, out, 1 );
You can suppress that warning by adding a // cppcheck-suppress uninitvar
comment above the function. For example:
// cppcheck-suppress uninitvar
stdlib_strided_dmeanvarpn( len, 1, x, 1, out, 1 );
I have the required packages in the expected paths, but I am still encountering an error like this while compiling the native add-on.
In packages involving C implementations, you need a manifest.json
file to inform node-gyp about the dependencies required for specific tasks. You should include only the necessary dependencies for compiling, benchmarking, and running examples. For example:
{
// Other sections above....
"confs": [
{
"task": "build",
"src": [
"./src/main.c"
],
"include": [
"./include"
],
"libraries": [],
"libpath": [],
"dependencies": [
"@stdlib/math/base/napi/unary",
"@stdlib/math/base/assert/is-nanf",
"@stdlib/constants/float32/pinf"
]
},
{
"task": "benchmark",
"src": [
"./src/main.c"
],
"include": [
"./include"
],
"libraries": [],
"libpath": [],
"dependencies": [
"@stdlib/math/base/assert/is-nanf",
"@stdlib/constants/float32/pinf"
]
},
{
"task": "examples",
"src": [
"./src/main.c"
],
"include": [
"./include"
],
"libraries": [],
"libpath": [],
"dependencies": [
"@stdlib/math/base/assert/is-nanf",
"@stdlib/constants/float32/pinf"
]
}
]
}
This config
specifies that we need to include @stdlib/math/base/napi/unary
, @stdlib/math/base/assert/is-nanf
, and @stdlib/constants/float32/pinf
for compiling the native add-on, while @stdlib/math/base/assert/is-nanf
and @stdlib/constants/float32/pinf
are required for running benchmarks and examples.
When should I use decimals in examples, benchmarks, and documentation, and when should I avoid them?
Decimals help us differentiate floating-point values from integers. For instance, in JavaScript, all numbers are treated as floating-point values, but it is still important to distinguish between integers and floating-point numbers for clarity. Consider the following C function:
double stdlib_strided_dnanvariancetk( const CBLAS_INT N, const double correction, const double *X, const CBLAS_INT strideX );
When calling this function in JavaScript, we expect the following usage:
var dnanvariancetk = require( '@stdlib/stats/base/dnanvariancetk' );
var Float64Array = require( '@stdlib/array/float64' );
var x = new Float64Array( [ 1.0, -2.0, NaN, 2.0 ] );
// Use decimals for floating-point values, not for integers.
var v = dnanvariancetk( 4, 1.0, x, 1 );
Notice that we used 1.0
as the second argument because it is a double-precision floating-point number. However, we did not use a decimal point for the first and fourth arguments, as they represent integers.
The best strategy is to go through other relevant PRs and follow their naming conventions. If not, use a concise and descriptive title that clearly conveys the purpose of your changes and follows the PR naming guidelines.
TODO: Can we add a link to the PR naming guidelines here?
Once you have created your PR, you can call the stdlib-bot to perform basic operations such as fixing lint errors, updating copyright years, or merging changes from the develop
branch into your PR. Some commonly used commands:
/stdlib update-copyright-years
- Updates copyright header years./stdlib lint-autofix
- Auto-fixes lint errors.
To see other available bot commands, comment /stdlib help
on your PR.
When you open a pull request or push changes to your feature branch, GitHub compares your feature branch against your develop
branch and shows all the differences. If your feature branch contains outdated or extra changes, they will appear in the PR, even if they are unrelated to your work.
To fix this, ensure that your feature branch is based on the latest develop
branch. You can do this by updating your local develop
branch and then merging it into your feature branch:
$ git checkout develop
$ git pull upstream develop
$ git push origin develop
$ git checkout feature-branch
$ git merge develop
After merging, push your changes to the remote repository:
$ git push origin feature-branch # git push also works
Note: When developing stdlib, we recommend using
merge
instead ofrebase
once a PR is open. Rebasing rewrites your branch history, which usually requires a force-push to update the remote branch. This can disrupt other contributors who are reviewing or collaborating on your PR. Since stdlib uses squash and merge for PRs, we don't require a clean, linear commit history. Merge commits are acceptable as long as your diff only contains relevant changes. If you want to learn more about rebasing/merging, you can refer to our Git guide.
Alternatively, you can call the stdlib-bot to merge changes from the develop
branch into your PR. To do this, comment /stdlib merge
on your PR.
We use GNU Make
as our development utility and task runner for tasks such as generating fixtures, compiling native add-ons, running tests, examples, and benchmarks. Some of the most frequently used make
commands that you will need in your workflow are:
$ make install
$ make init
$ make install-node-addons NODE_ADDONS_PATTERN="math/base/special/abs"
- Julia
$ make test-fixtures-julia TESTS_FIXTURES_FILTER=".*/path/to/package/.*"
- Python
$ make test-fixtures-python TESTS_FIXTURES_FILTER=".*/path/to/package/.*"
For more make
commands, refer to the test fixtures documentation.
$ make TESTS_FILTER=".*/math/base/special/abs/.*" test
$ make EXAMPLES_FILTER=".*/math/base/special/abs/.*" examples
For more make
commands, refer to the documentation on running examples.
$ make BENCHMARKS_FILTER=".*/math/base/special/abs/.*" benchmark
For more make
commands, refer to the documentation on running benchmarks.