coreutils / gnulib /HACKING
AryaWu's picture
Upload folder using huggingface_hub
78d2150 verified
Information for GNU Gnulib maintainers and contributors
*******************************************************
Using git
=========
* We don't use topic branches. Changes are usually small enough that
they can be committed directly to the master branch, after appropriate
testing.
* We maintain stable branches, though, as described in the documentation:
https://www.gnu.org/software/gnulib/manual/html_node/Stable-Branches.html
When backporting a commit to a stable branch of the last year, be sure
to update the copyright year of each modified file (since we don't run
"make update-copyright" on the stable branches).
* We use a linear git history — no merges. To work in this setting, it's
recommended that you configure git with 'git config pull.rebase = true'.
* Before pushing a commit, it is highly recommended that you review it in
its entirety. The easiest ways to do so are
* to run
$ git format-patch -1
and then read the patch in an editor that has syntax-colouring of patch
files, or
* to run
$ gitk
* We update the ChangeLog by hand. The commit message is usually identical
to the ChangeLog entry, with the date and author line removed, with
the leading tabs removed, and with a blank line after the commit's
summary line.
In order to work efficiently with ChangeLog files, it is recommended that
you configure git to use the git-merge-changelog driver; see the instructions
in the lib/git-merge-changelog.c file.
Note: This driver reasonably keeps the ChangeLog entries together; however,
it does not always keep them in the order you would desire. For example,
when you had prepared a commit, you try to "git push" it but that fails due
to someone else's commit that came earlier, what you need to do is:
1. $ git pull
2. Verify that your ChangeLog entry is still the top-most one.
3. If it is not, then edit ChangeLog to move it to the top, and
$ git commit --amend ChangeLog
4. $ gitk
5. $ git push
* When you commit a contributor's patch, please
- add a reasonable ChangeLog entry in the usual style (meaningful
summary line and detailed change list),
- if the contribution is so small that it does not require a
copyright assignment (cf.
https://www.gnu.org/prep/maintain/html_node/Legally-Significant.html )
add a line:
Copyright-paperwork-exempt: Yes
- use the 'git commit' option --author="Contributor Name <email@address>"
License Notices
===============
In *.m4 files, use a notice like this:
dnl Copyright (C) YEARS Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl with or without modifications, as long as this notice is preserved.
dnl This file is offered as-is, without any warranty.
In lib/, tests/, build-aux/ files, except those that are shared with glibc,
use the license notices from etc/license-notices/ . This avoids gratuitous
differences in wording, as well misunderstandings when a license notice
would say "This program ...".
Test Suite
==========
When adding a module, add a unit test module as well. This is our best
chance to catch portability problems.
A unit test can have many sub-tests. Try to make the sub-tests independent
of each other, so that it becomes easy to disable some sub-tests by enclosing
them in #if 0 ... #endif.
The main() function's exit code meaning is:
- 0: PASS
- 77: SKIP; you should print the reason why the test is skipped.
- 99: ERROR, i.e. test framework error
- any other exit code < 126: FAIL
In tests that #include "macros.h" and use the ASSERT macro:
The main() function should, before it returns 0 (for PASS) or 77 (for SKIP)
test the value of test_exit_status and return that instead. So:
- not
return 0;
but instead
return test_exit_status;
- not
return result; // where result can be 0 or 1
but instead
return (result ? result : test_exit_status);
- not
fputs ("Skipping test: <reason>\n", stderr);
return 77;
but instead
if (test_exit_status != EXIT_SUCCESS)
return test_exit_status;
fputs ("Skipping test: <reason>\n", stderr);
return 77;
Only at the beginning of the main() function, when ASSERT has not yet been
invoked, we know that test_exit_status must be zero and can therefore write
fputs ("Skipping test: <reason>\n", stderr);
return 77;
directly.
Maintaining high quality
========================
It is a good idea to occasionally create a testdir of all of Gnulib:
$ rm -rf ../testdir-all; ./gnulib-tool --create-testdir --dir=../testdir-all --with-c++-tests --without-privileged-tests `./all-modules`
and test this directory on various platforms:
- Linux/glibc systems,
- Linux/musl systems,
- macOS,
- FreeBSD,
- NetBSD,
- OpenBSD,
- AIX,
- Solaris 10 and 11,
- Cygwin,
- Haiku,
- Android,
- and other platforms of your choice.
There are two continuous integrations that regularly perform this testing:
* On a Linux/glibc system only:
https://gitlab.com/gnulib/gnulib-ci
This one will catch only the most blatant mistakes.
* On many platforms:
https://github.com/gnu-gnulib/ci-testdir-check/actions
This one runs on many platforms, currently (as of June 2024):
- Ubuntu GNU/Linux 22.04
- CentOS GNU/Linux 7
- Alpine Linux
- macOS 11, 12, 13 (all x86_64)
- macOS 14 (arm64)
- FreeBSD 14.0
- NetBSD 10.0
- OpenBSD 7.5
- Solaris 11.4
- Solaris 11 OmniOS
- Cygwin 3.3.6 (32 bit) and 3.5.3 (64 bit)
- mingw (32 bit and 64 bit)
- MSVC (32 bit and 64 bit)
and also
- on Ubuntu GNU/Linux 22.04 with clang's UBSAN and ASAN sanitizers.
This one catches real portability problems.
Note that the following platforms are not covered and thus still require
occasional manual testing:
- AIX
- Solaris 10
- Haiku
- Android
- and other platforms of your choice.
Warning Options
===============
For packages that use Gnulib, we recommend to use the 'warnings' or
'manywarnings' module, as documented in
https://www.gnu.org/software/gnulib/manual/html_node/warnings.html
https://www.gnu.org/software/gnulib/manual/html_node/manywarnings.html
When building Gnulib testdirs, e.g. when preparing a Gnulib patch,
there are three possible approaches:
* The simplest approach, which warns about the most common mistakes, is to
use GCC's -Wall option, both for C and C++ compilation units. Just set
$ ./configure CPPFLAGS="-Wall"
$ make
You should generally fix all compiler warnings that you see from this
approach.
* If you are developing on a glibc system and have GCC version 15 binaries
available, here's a recipe that will find more mistakes, but is nearly
as easy to use. Here, different warning options are needed for C and
for C++:
$ WARN_GCC15=`echo '
-fanalyzer
-Wall
-Warith-conversion
-Wcast-align=strict
-Wdate-time
-Wduplicated-cond
-Wextra
-Wflex-array-member-not-at-end
-Wformat-signedness
-Winit-self
-Winvalid-pch
-Wlogical-op
-Wmaybe-musttail-local-addr
-Wmissing-include-dirs
-Wopenmp-simd
-Woverlength-strings
-Wpacked
-Wpointer-arith
-Wstrict-overflow
-Wsuggest-final-methods
-Wsuggest-final-types
-Wsync-nand
-Wsystem-headers
-Wtrampolines
-Wuninitialized
-Wunknown-pragmas
-Wunsafe-loop-optimizations
-Wvariadic-macros
-Wvector-operation-performance
-Wwrite-strings
-Warray-bounds=2
-Wattribute-alias=2
-Wformat-overflow=2
-Wformat-truncation=2
-Wshift-overflow=2
-Wunused-const-variable=2
-Wvla-larger-than=4031
-Wno-empty-body
-Wno-analyzer-allocation-size
-Wno-analyzer-fd-double-close
-Wno-analyzer-double-fclose
-Wno-analyzer-double-free
-Wno-analyzer-fd-leak
-Wno-analyzer-fd-use-after-close
-Wno-analyzer-fd-use-without-check
-Wno-analyzer-free-of-non-heap
-Wno-analyzer-malloc-leak
-Wno-analyzer-mismatching-deallocation
-Wno-analyzer-null-argument
-Wno-analyzer-null-dereference
-Wno-analyzer-out-of-bounds
-Wno-analyzer-possible-null-argument
-Wno-analyzer-possible-null-dereference
-Wno-analyzer-use-after-free
-Wno-analyzer-use-of-pointer-in-stale-stack-frame
-Wno-analyzer-use-of-uninitialized-value
-Wno-analyzer-va-arg-type-mismatch
-Wno-attribute-warning
-Wno-cast-align
-Wno-clobbered
-Wno-dangling-pointer
-Wno-format
-Wno-implicit-fallthrough
-Wno-maybe-uninitialized
-Wno-missing-field-initializers
-Wno-restrict
-Wno-sign-compare
-Wno-switch
-Wno-type-limits
-Wno-unused-parameter
' | tr -d '\n' | sed -e 's/ */ /g'`
$ WARN_CFLAGS_GCC15="$WARN_GCC15 -Wmissing-variable-declarations -Wnested-externs -Wshadow=local -Wno-discarded-qualifiers"
$ WARN_CXXFLAGS_GCC15="$WARN_GCC15 -Wno-cpp"
$ ./configure CFLAGS="-O2 -g $WARN_CFLAGS_GCC15" CXXFLAGS="-O2 -g $WARN_CXXFLAGS_GCC15"
$ make
You should generally fix all compiler warnings that you see from this
approach, or report when this approach produced a pointless warning
(so that we can fix the value of WARN_GCC15 above).
* If you are developing on a glibc system and have GCC version 15 binaries
available: Here's a recipe that will find even more mistakes, but it
requires that you are willing to filter out and ignore pointless warnings.
$ WARN_GCC15=`echo '
-fanalyzer
-Wall
-Warith-conversion
-Wcast-align=strict
-Wdate-time
-Wduplicated-cond
-Wextra
-Wflex-array-member-not-at-end
-Wformat-signedness
-Winit-self
-Winvalid-pch
-Wlogical-op
-Wmaybe-musttail-local-addr
-Wmissing-include-dirs
-Wnull-dereference
-Wopenmp-simd
-Woverlength-strings
-Wpacked
-Wpointer-arith
-Wstrict-overflow
-Wsuggest-attribute=format
-Wsuggest-final-methods
-Wsuggest-final-types
-Wsync-nand
-Wsystem-headers
-Wtrampolines
-Wuninitialized
-Wunknown-pragmas
-Wunsafe-loop-optimizations
-Wvariadic-macros
-Wvector-operation-performance
-Wwrite-strings
-Warray-bounds=2
-Wattribute-alias=2
-Wformat-overflow=2
-Wformat=2
-Wformat-truncation=2
-Wimplicit-fallthrough=5
-Wshift-overflow=2
-Wunused-const-variable=2
-Wvla-larger-than=4031
-Wno-empty-body
-Wno-analyzer-double-fclose
-Wno-analyzer-double-free
-Wno-analyzer-free-of-non-heap
-Wno-analyzer-malloc-leak
-Wno-analyzer-null-argument
-Wno-analyzer-null-dereference
-Wno-analyzer-use-after-free
-Wno-attribute-warning
-Wno-cast-align
-Wno-clobbered
-Wno-format-nonliteral
-Wno-sign-compare
-Wno-type-limits
-Wno-unused-parameter
' | tr -d '\n' | sed -e 's/ */ /g'`
$ WARN_CFLAGS_GCC15="$WARN_GCC15 -Wmissing-variable-declarations -Wnested-externs -Wshadow=local"
$ WARN_CXXFLAGS_GCC15="$WARN_GCC15 -Wno-cpp"
$ ./configure CFLAGS="-O2 -g $WARN_CFLAGS_GCC15" CXXFLAGS="-O2 -g $WARN_CXXFLAGS_GCC15"
$ make
With this approach, use your own judgement whether to fix warnings
arising from your new code or not.
Do *not* submit patches to silence warnings from existing code:
- For these warnings, often the cure will be worse than the disease.
- Some of the warnings are false positives. Rather than silencing
these warnings, we prefer to report them in the GCC bug tracker
and wait until they are fixed in a future GCC release.
Similarly, for clang version 20 you can use the following recipe, that uses
selected warning options from
https://releases.llvm.org/20.1.0/tools/clang/docs/DiagnosticsReference.html :
$ WARN_CLANG20=`echo '
-Wall
-Wanon-enum-enum-conversion
-Warc-repeated-use-of-weak
-Warray-bounds-pointer-arithmetic
-Warray-parameter
-Watomic-properties
-Wauto-decl-extensions
-Wbinary-literal
-Wbit-int-extension
-Wbitfield-enum-conversion
-Wbitwise-op-parentheses
-Wbool-operation
-Wc++-compat
-Wc23-compat
-Wc23-extensions
-Wc2x-compat
-Wc2x-extensions
-Wc23-extensions
-Wc99-compat
-Wc99-designator
-Wc99-extensions
-Wcalled-once-parameter
-Wcast-function-type
-Wchar-subscripts
-Wcomment
-Wcompletion-handler
-Wcomplex-component-init
-Wcompound-token-split
-Wconsumed
-Wconversion
-Wcstring-format-directive
-Wcuda-compat
-Wdate-time
-Wdelimited-escape-sequence-extension
-Wdeprecated
-Wdeprecated-dynamic-exception-spec
-Wdeprecated-implementations
-Wdeprecated-this-capture
-Wdeprecated-writable-strings
-Wdirect-ivar-access
-Wdocumentation
-Wdocumentation-deprecated-sync
-Wdocumentation-html
-Wdocumentation-pedantic
-Wdocumentation-unknown-command
-Wdollar-in-identifier-extension
-Wduplicate-decl-specifier
-Wduplicate-enum
-Wduplicate-method-arg
-Wduplicate-method-match
-Wdynamic-exception-spec
-Wembedded-directive
-Wempty-init-stmt
-Wempty-translation-unit
-Wenum-compare-conditional
-Wenum-conversion
-Wenum-enum-conversion
-Wenum-float-conversion
-Wexit-time-destructors
-Wexpansion-to-defined
-Wexplicit-ownership-type
-Wextra
-Wextra-semi
-Wflexible-array-extensions
-Wfloat-overflow-conversion
-Wfloat-zero-conversion
-Wfor-loop-analysis
-Wformat
-Wformat-pedantic
-Wformat-type-confusion
-Wformat=2
-Wfour-char-constants
-Wframe-address
-Wfuse-ld-path
-Wfuture-attribute-extensions
-Wgcc-compat
-Wgnu
-Wgnu-anonymous-struct
-Wgnu-auto-type
-Wgnu-case-range
-Wgnu-complex-integer
-Wgnu-compound-literal-initializer
-Wgnu-conditional-omitted-operand
-Wgnu-designator
-Wgnu-empty-initializer
-Wgnu-empty-struct
-Wgnu-flexible-array-initializer
-Wgnu-flexible-array-union-member
-Wgnu-folding-constant
-Wgnu-imaginary-constant
-Wgnu-label-as-value
-Wgnu-line-marker
-Wgnu-null-pointer-arithmetic
-Wgnu-offsetof-extensions
-Wgnu-pointer-arith
-Wgnu-redeclared-enum
-Wgnu-statement-expression
-Wgnu-statement-expression-from-macro-expansion
-Wgnu-union-cast
-Wgnu-zero-line-directive
-Wgnu-zero-variadic-macro-arguments
-Wheader-hygiene
-Widiomatic-parentheses
-Wignored-qualifiers
-Wimplicit
-Wimplicit-fallthrough
-Wimplicit-fallthrough-per-function
-Wimplicit-function-declaration
-Wimplicit-int
-Wimplicit-retain-self
-Wimport-preprocessor-directive-pedantic
-Wincomplete-module
-Winconsistent-missing-destructor-override
-Winfinite-recursion
-Wint-in-bool-context
-Winvalid-or-nonexistent-directory
-Winvalid-utf8
-Wkeyword-macro
-Wlanguage-extension-token
-Wlocal-type-template-args
-Wlogical-op-parentheses
-Wlong-long
-Wloop-analysis
-Wmain
-Wmax-tokens
-Wmethod-signatures
-Wmicrosoft
-Wmicrosoft-anon-tag
-Wmicrosoft-charize
-Wmicrosoft-comment-paste
-Wmicrosoft-cpp-macro
-Wmicrosoft-end-of-file
-Wmicrosoft-enum-value
-Wmicrosoft-exception-spec
-Wmicrosoft-fixed-enum
-Wmicrosoft-flexible-array
-Wmicrosoft-redeclare-static
-Wmisleading-indentation
-Wmismatched-tags
-Wmissing-braces
-Wmissing-method-return-type
-Wmost
-Wmove
-Wnested-anon-types
-Wnewline-eof
-Wnon-gcc
-Wnon-modular-include-in-framework-module
-Wnon-modular-include-in-module
-Wnon-virtual-dtor
-Wnonportable-system-include-path
-Wnull-pointer-arithmetic
-Wnull-pointer-subtraction
-Wnullability-extension
-Wnullable-to-nonnull-conversion
-Wopenmp
-Wover-aligned
-Woverlength-strings
-Woverloaded-virtual
-Woverriding-method-mismatch
-Wpacked
-Wpacked-non-pod
-Wparentheses
-Wpedantic
-Wpedantic-core-features
-Wpessimizing-move
-Wpointer-arith
-Wpoison-system-directories
-Wpragma-pack
-Wpragma-pack-suspicious-include
-Wpragmas
-Wpre-c11-compat
-Wpre-c23-compat
-Wpre-c2x-compat
-Wpre-c2y-compat
-Wpre-openmp-51-compat
-Wprofile-instr-missing
-Wquoted-include-in-framework-header
-Wrange-loop-analysis
-Wrange-loop-bind-reference
-Wrange-loop-construct
-Wreceiver-forward-class
-Wredundant-move
-Wredundant-parens
-Wreorder
-Wreorder-ctor
-Wreserved-attribute-identifier
-Wreserved-user-defined-literal
-Wretained-language-linkage
-Wselector
-Wselector-type-mismatch
-Wself-assign
-Wself-assign-overloaded
-Wself-move
-Wsemicolon-before-method-body
-Wshadow-all
-Wshadow-field
-Wshadow-field-in-constructor
-Wshadow-field-in-constructor-modified
-Wshadow-uncaptured-local
-Wshift-sign-overflow
-Wsigned-enum-bitfield
-Wsometimes-uninitialized
-Wsource-uses-openacc
-Wsource-uses-openmp
-Wspir-compat
-Wstatic-in-inline
-Wstrict-potentially-direct-selector
-Wstrict-selector-match
-Wstring-concatenation
-Wstring-conversion
-Wsuggest-destructor-override
-Wsuggest-override
-Wsuper-class-method-mismatch
-Wtautological-bitwise-compare
-Wtautological-compare
-Wtautological-constant-in-range-compare
-Wtautological-negation-compare
-Wtautological-overlap-compare
-Wtautological-type-limit-compare
-Wtautological-unsigned-char-zero-compare
-Wtautological-unsigned-enum-zero-compare
-Wtautological-unsigned-zero-compare
-Wtautological-value-range-compare
-Wthread-safety
-Wthread-safety-analysis
-Wthread-safety-attributes
-Wthread-safety-beta
-Wthread-safety-negative
-Wthread-safety-precise
-Wthread-safety-reference
-Wthread-safety-verbose
-Wtype-limits
-Wunaligned-access
-Wundeclared-selector
-Wundef-prefix
-Wundefined-func-template
-Wundefined-internal-type
-Wundefined-reinterpret-cast
-Wunguarded-availability
-Wuninitialized
-Wuninitialized-const-reference
-Wunknown-pragmas
-Wunnamed-type-template-args
-Wunneeded-internal-declaration
-Wunneeded-member-function
-Wunreachable-code-fallthrough
-Wunreachable-code-loop-increment
-Wunsupported-dll-base-class-template
-Wunused
-Wunused-but-set-parameter
-Wunused-but-set-variable
-Wunused-const-variable
-Wunused-exception-parameter
-Wunused-function
-Wunused-label
-Wunused-lambda-capture
-Wunused-local-typedef
-Wunused-member-function
-Wunused-private-field
-Wunused-property-ivar
-Wunused-template
-Wunused-variable
-Wvariadic-macros
-Wvector-conversion
-Wvla-cxx-extension
-Wweak-template-vtables
-Wweak-vtables
-Wzero-length-array
-Wno-bitwise-instead-of-logical
-Wno-c11-extensions
-Wno-cast-function-type-strict
-Wno-float-conversion
-Wno-format-nonliteral
-Wno-gnu-include-next
-Wno-implicit-float-conversion
-Wno-implicit-int-conversion
-Wno-implicit-int-float-conversion
-Wno-include-next-absolute-path
-Wno-missing-field-initializers
-Wno-reserved-macro-identifier
-Wno-shadow
-Wno-shorten-64-to-32
-Wno-sign-compare
-Wno-sign-conversion
-Wno-strict-prototypes
-Wno-switch
-Wno-unused-parameter
-Wno-tautological-constant-out-of-range-compare
-Wno-tautological-type-limit-compare
-Wno-tautological-unsigned-zero-compare
-Wno-tautological-value-range-compare
-Wno-unused-command-line-argument
-Wno-user-defined-warnings
' | tr -d '\n' | sed -e 's/ */ /g'`
$ ./configure CFLAGS="-O2 -g $WARN_CLANG20" CXXFLAGS="-O2 -g $WARN_CLANG20"
$ make
Again, use your own judgement to determine whether to fix or ignore a
specific warning.
Maintaining link dependencies
=============================
Each module has a section "Link:", that contains the linker options that
a program, that makes use of the module, needs to use, in order to avoid
a link error. Unless empty, this field contains one or more variable
references, because linker options are platform dependent. A gnulib-tool
invocation lists these linker options to the package maintainer, so that
they can make use of these options in the *_LDFLAGS in their package's
Makefile.am.
Of course, the unit tests uses these linker options.
Often the link dependencies for module 'foo' follows this naming
convention: $(FOO_LIB). For example, there are variables references
$(MBRTOWC_LIB) $(SETLOCALE_LIB).
Typically, when you make a code change in a module and accordingly
define a variable for its linker options in the corresponding *.m4 file,
you also need to update the linker options of all modules that depend
on it:
$ ./gnulib-tool --extract-dependents foo
and the linker options of all modules that depend on these, etc.:
$ ./gnulib-tool --extract-recursive-dependents foo
The use of a variable per module avoids the need for an avalanche of
changes.
When you notice a link error of a program, you typically fix it in three
steps:
1. Ask "Which library does the program need to link with?"
You answer this by consulting documentation and man pages, as well
as by use of "nm --dynamic /lib/libxyz.so".
2. Ask "From which autoconf variable do I get this library option?"
You answer this by searching the *LIB* values in config.status:
$ grep LIB config.status
3. Finally you add a reference to that variable to the *_LIB variable
of your module. Or, if your module does not have such a variable
so far, you introduce such a variable and make sure to update all
dependents to make use of it (see above).
Information for gnulib-tool maintenance
***************************************
Running the unit tests
======================
The unit tests of gnulib-tool reside in the maint-tools repository, that is a
satellite repository of the main gnulib repository. Instructions how to obtain
it are in https://savannah.gnu.org/git/?group=gnulib .
To run the unit tests of gnulib-tool.sh:
$ cd maint-tools/gnulib-tool-tests/
$ GNULIB_TOOL_IMPL=sh ./test-all.sh
To run the unit tests of gnulib-tool.py:
$ cd maint-tools/gnulib-tool-tests/
$ GNULIB_TOOL_IMPL=py ./test-all.sh
It is *mandatory* that you run the test suite before pushing any change to
gnulib-tool.sh or gnulib-tool.py! If you fail to do so, and your change contains
a bug, it will start to affect users immediately.
Debugging the Python implementation of gnulib-tool
==================================================
With Eclipse and PyDev as IDE
-----------------------------
* Download and configuration:
- Eclipse IDE from https://www.eclipse.org/downloads/packages/
(either the build for Java or for C/C++ should work fine;
either use the Eclipse Installer program at the top of the page,
or one of the individual download links below).
- PyDev from https://www.pydev.org/download.html
section "Install as Plugin".
(Don't use LiClipse, since the license costs money.)
- Follow https://www.pydev.org/manual_101_install.html,
replacing http://www.pydev.org/updates
with https://www.pydev.org/updates
- Once installed, restart the IDE.
- Window > Preferences > PyDev > Interpreters > Python Interpreter:
New > path: /usr/bin/python3
- Window > Preferences > PyDev > Editor > Code Analysis:
Others > Redefinition of builtin symbols: Ignore
* Create a project:
Let GNULIB_DIR be my gnulib checkout.
- File > New > Project... > PyDev > PyDev Project. Call it 'gnulib-tool'.
Note that this is a project inside the Eclipse workspace, so far
unrelated to the GNULIB_DIR.
- Popup menu > New > Link to Existing Source
Name: gnulib
Path: <GNULIB_DIR>
* Create a run configuration:
- Run > Run Configurations... > Python Run
Popup menu > New configuration
Name: gnulib-tool.py
Main > Project: gnulib-tool
Main > Main Module: ${workspace_loc:gnulib-tool/gnulib/.gnulib-tool.py}
Arguments > Program arguments: --help
- Test it: Run this configuration.
* Create a debug configuration:
- Run > Debug Configurations... > gnulib-tool.py
Popup menu > Duplicate
- In the duplicate, set
Arguments > Working directory: /tmp/oath-toolkit/lib
Arguments > Program arguments: --add-import
* Debug it:
- Open GLImport.py.
- On the left-hand border of this editor, do "Add breakpoint".
- Run > Debug Configurations... > pick the duplicate. Press Debug.
Maintaining high quality
========================
There is a continuous integration of gnulib-tool.py that runs the unit tests,
at https://gitlab.com/gnulib/gnulib-tool-ci/ .