GPIOD_VERSION_STRING environment variable is no longer used by setup.py.
It's been replaced by reading the version from the variable defined in
version.py.
libgpiod C++ types are not meant to be inherited from. They already don't
even provide virtual destructors so mark them explicitly as final. With
that the destructors of throwable types can also be made non-virtual.
If info is NULL in one of the line-info test cases, we'll still try to
read its property leading to an abort() triggered from assert(info). Just
bail out of the test function if gpiod_chip_get_line_info() fails.
tests: add line value enums for gpiosim GLib wrapper
libgpiosim has a dedicated enum type for line values but the GLib wrapper
still uses magic numbers (0 and 1). Add an enum type for the wrapper and
use it across all test cases.
bindings: cxx: drop the re-export guard of visible symbols
The ifdef guard that changes the definition of GPIOD_CXX_API between
"default" and "hidden" is there to prevent libraries that would include
gpiod.hpp from re-exporting libgpiodcxx symbols.
Unfortunately the hidden linkage only works for translation units within
the same ELF object. At static linking time we must always mark the
throwable types as visible or we'll get the following errors:
/usr/bin/ld: tests-chip.o:(.data+0x0): undefined reference to `typeinfo for gpiod::chip_closed'
/usr/bin/ld: tests-line-request.o:(.data+0x0): undefined reference to `typeinfo for gpiod::request_released'
/usr/bin/ld: .libs/gpiod-cxx-test: hidden symbol `_ZTIN5gpiod11chip_closedE' isn't defined
/usr/bin/ld: final link failed: bad value
On top of that we actually WANT to re-export typeinfo for throwable types
as they can be propagated to external callers when an exception is thrown.
The above error can only be triggered on clang. GCC seems to be
incorrectly omitting the "hidden" attribute in this case.
Fix it by moving to a later version of bindgen, which updates the types
of few of the arguments to the FFI helpers and so required changes to
few of explicit type conversions.
twalk_r() is a GNU extension for the binary search tree API. Musl libc
doesn't provide it and after inquiring with the maintainer it turned out
it won't provide it anytime soon as musl strives to only implement well
standardized functions.
In order to not limit building libgpiosim and tests to glibc only, let's
replace twalk_r() with twalk() and use global variables for the state.
It's not a big deal as we're already using a global root node and a mutex
to protect it.
The DESTDIR variable can be used to perform a staged installation. The
package should be configured as if it was going to be installed in its
final location (e.g., --prefix /usr), but when running make install, the
DESTDIR should be set to the absolute name of a directory into which the
installation will be diverted. From this directory it is easy to review
which files are being installed where, and finally copy them to their
final location by some means.
Prefix $(prefix) with $(DESTDIR) when calling setup.py.
Reported-by: Peter Robinson <pbrobinson@gmail.com> Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org> Reviewed-by: Peter Robinson <pbrobinson@gmail.com> Tested-by: Peter Robinson <pbrobinson@gmail.com>
bindings: cxx: fix building gpiod::timestamp with clang
Clang's system_clock implementation uses microseconds resolution by
default and we fail to construct a time_point out of chrono::nanoseconds
as the library prohibits us from accidentally losing information when
casting the latter to the former. Use nanoseconds explicitly as the
resolution of the realtime timestamp.
uint is an old compatibility name that GCC still provides but clang
doesn't. Use unsigned int instead.
Fixes: 8ffb6489286f ("tools: line name focussed rework") Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org> Reviewed-by: Kent Gibson <warthog618@gmail.com>
tests: rework error handling and stop overusing g_error()
GLib recommends using g_error() only for programming errors and
unrecoverable situations. It calls abort() and triggers a core dump. This
means that if we encounter an error when running a test case, we'll
exit immediately and leave a "leaked" GPIO simulator in configfs.
Rework the error handling: use g_error() only when a programming bug is
encountered (e.g. invalid enum value) while everywhere else use the
regular GError-based error handling. This way, in case of an error in
libgpiosim, we'll simply fail the current test case and release all
resources as usual.
In order not to pollute the test cases with error handling, let's hide the
actual error checking behind macros for g_gpiosim_chip_new() and
g_gpiosim_chip_get_value(). For g_gpiosim_chip_set_pull() let's just emit
a log and do nothing as the test case in question will inevitably fail if
the expected value is not correctly read back.
In order for the chip to get a failing constructor, we need to link the
test-suite against the entire libgio, not only libgobject (for the
GInitable interface).
Revert "tests: consistently use GLib types in tests"
GLib recommends to use standard library's int as the return type for
main() and g_test_run() also returns int, not gint. Revert the commit
that made main() return gint.
tests: drop the .dispose() method from gpiosim-glib's chip class
The .dispose() method should be used to drop references to any other
GObjects while .finalize() should free any remaining memory. While we are
dropping references in .dispose(), these are references to the libgpiosim
objects that are also guaranteed to always be at most equal 1. Move the
reference drops to .finalize() and remove .dispose() entirely.
tests: add a missing call to parent's implementation of .constructed()
In GObject inheriting classes must call the parent's implementation of
"virtual" methods manually. Add a missing call to parent's .constructed()
method in the GLib wrapper of libgpiosim.
gpioset: use #ifdef instead of #if with GPIOSET_INTERACTIVE
We're not setting GPIOSET_INTERACTIVE to any specific value that we'd
want to check so be consistent and use #ifdef everywhere to simply check
if it's defined or not.
g_variant_new() returns a floating reference that must be converted to
a full reference before returning or else we may get weird reference
counting errors.
We have two helpers that do the same thing: given a key and a map, they
return the associated value or throw an exception if the map doesn't
contain it. The difference is just in the type of the exception. Remove
one and reuse the other. While at it: modify the names a bit for better
readability - especially the mapping function which is not limited to
just mapping enum types.
There are two leftover instances where we return raw C pointers from
local functions. For safety and consistency with the rest of the code
convert those functions to return unique_ptr.
bindings: rust: provide line_config.set_output_values()
Add a new function to line config allowing to set a list of output values
for requested lines. This works very similarily to the C++ version of the
new C interface.
In C++ bindings we can chain the mutators as they all return a reference
to the object they modify. It's a common practice to allow that in Rust
too so make all mutators that don't already do it return a mutable
reference to self.
It's also logically incorrect to make mutators borrow an immutable
reference to self. Even if that builds - as we're fiddling with C
pointers - it could change in the future. It's fine for getters but
setters should all use mutable references.
bindings: python: add the output_values argument to Chip.request_lines()
Add a new optional argument to Chip.request_lines() called output_values.
It accepts a dictionary of mappings between line names or offsets to the
output values the requested lines should be set to at request-time.
core: provide gpiod_line_config_set_output_values()
Currently if user wants to use the same settings for a set of requested
lines with the exception of the output value - they need to go through
hoops by updating the line settings object and adding it one by one to
the line config. Provide a helper function that allows to set a global
list of output values that override the settings. For details on the
interface: see documentation in this commit.
We have two functions in the C API that allow users to retrieve a list
of offsets from objects: gpiod_line_request_get_offsets() and
gpiod_line_config_get_offsets(). Even though they serve pretty much the
same purpose, they have different signatures and one of them also
requires the user to free the memory allocated within the libgpiod
library with a non-libgpiod free() function.
Unify them: make them take the array in which to store offsets and the
size of this array. Make them return the number of offsets actually
stored in the array and make them impossible to fail. Change their names
to be more descriptive and in the case of line_config: add a new function
that allows users to get the number of configured offsets.
Update the entire tree to use the new interfaces.
For rust bindings: also unify the line config interface to return a map
of line settings like C++ bindings do instead of having a function to
get settings by offset. A map returned from a single call is easier to
iterate over with a for loop than using an integer and calling the
previous line_settings() method.
The rust crates builds fine when built with the 'make' command, as
static linking works fine. But when referenced from a remote rust crate,
it gives following error:
error: could not find native static library `gpiod`, perhaps an -L flag is missing?
This happens since we only support 'static' LIB-KIND currently. Remove
the same to allow others to work too.
bindings: rust: make request_config optional in Chip.request_lines()
Request config is not necessary to request lines. In C API we accept
a NULL pointer, in C++ it's not necessary to assign a request_config
to the request builder, in Python the consumer and event buffer size
arguments are optional. Let's make rust bindings consistent and not
require the request config to be always present. Convert the argument
in request_lines to Option and update the rest of the code.
We're using testing wrong variables in the reset_config test case. We
should be checking the retrieved0 settings which are read back from
the line config object.
Implement the copy operator for line_settings. We have a copy() method
for line settings in C API while in C++ it's useful to copy line_settings
returned in an std::map from line_config.get_line_settings().
Makefile.am delegates the build of the python extension to its
setup.py file, which references the extension .c files relative to the
source dir. This makes it impossible to build in a directory that is
different from the source directory (for example, for PC and ARM but
from the same source).
* Invoke setup.py from $(srcdir)
* Modify setup.py to pick up .c files relative from setup.py's own
directory.
Currently we almost never check the validity of pointers passed to the
core C API routines. While we cannot know if a non-NULL pointer points
to an actual object, we can at least verify that it is not NULL before
dereferencing it.
Conceptually we can think of two categories of pointers in libgpiod:
First, there are the objects we manipulate using the API. These are
normally the first arguments in any given method and they are only
instantiated inside the library and never dereferenced by the user.
They should always be valid, so passing a NULL pointer here should
always lead to a crash. Currently it will take the form of a segfault
at the moment of dereference but with this change, we make the user
program abort() with the stack trace pointing right at the offender.
The second category would be pointers to objects that are logically
parameters of methods i.e. not their first argument. Example is:
gpiod_chip_request_lines(chip, req_cfg, line_cfg) (whose logical OOP
version would be: chip->request_lines(req_cfg, line_cfg)). Here we
accept a NULL req_cfg but we'll segfault on a NULL line_cfg. For
consistency: don't crash here but instead return -1 and set errno
to EINVAL. Same everywhere else.
gpiosim: fix error reporting in gpiosim_bank_hog_line()
We don't return errno numbers from public functions - we set errno and
indicate an error by returning -1 or NULL depending on the function
signature. Make gpiosim_bank_hog_line() consistent with that behavior.
configure: restore AS_IF() when using PKG_CHECK_MODULES()
pkg-config fails if we only try to build the tests without building the
tools. I'm not sure why that happens and can't find any other fix than
restore the AS_IF() for the 'with_tools' block.
Surprisingly: PKG_CHECK_MODULES() works fine elsewhere. Add a FIXME in
the configure.ac and investigate later.
Fixes: 68dd8c6e5edb ("configure: drop AS_IF() macros") Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
core: rename gpiod_version_string() to gpiod_api_version()
Instead of telling the user what type this function returns (they can
check it by looking at the prototype), tell them what the return value
actually represents.
configure: improve the header and library function checks
The project is often cross-compiled for embedded systems with all kinds
of wonky toolchains so update configure.ac with checks for less standard
functions and headers. While at it: rearrange the existing checks a bit
so that we only check for headers and symbols when we need them for
current build configuration.
build: use LIBEDIT_CFLAGS when building gpioset with interactive mode
The Makefile doesn't include the libedit CLFLAGS when building gpioset
with interactive mode enabled. This can lead to a build failure if the
header is not in the standard location (/usr/include/editline/readline.h).
AS_IF() is much less readable than a regular if/else and it's only called
for by docs if the code inside the expansion uses AC_REQUIRE(). Convert
AS_IF() occurrences to standard if/else syntax.
The fcntl.h header is needed for openat() and mkdirat() that the gpiosim
code uses. It seems to be pulled in indirectly on most toolchains but for
the sake of correctness, include it explicitly.
treewide: add missing commas to enums and struct definitions
The code is not consistent with regard to following the last element in
enums and struct definitions with a comma. Unless the last element is
guaranteed not to change (e.g. '{ }', or NULL), follow it with a comma
treewide to avoid churn in git when adding new values.
When we run the test suite by calling the __main__ function of the module,
the name of the process as visible in the system becomes "python". Let's
set it to "python-gpiod" before running the tests. This way gpiosim will
name its configfs attributes appropriately.
program_invocation_short_name is set once at the program's start. If we
change the process name using prctl(), we need to retrieve it using the
same system call as program_invocation_short_name will not be updated.
If we set the number of lines to x, set line names or hogs for lines
from 0 through x, then set the number of lines to (x - y), we will not
unlink all the line directories as we only iterate up to num_lines in
bank_release().
Allocate a small structure for every line we create a lineX directory
for and iterate over it in bank_release() to know exactly which ones
need freeing.
bindings: python: decouple the version of the bindings from libgpiod API version
Python bindings now have their own setup.py script and can be built
separately from the rest of the code-base. Let's decouple the python
package version from libgpiod API (but let's keep a module attribute
containing the API version) by introducing a version.py submodule that
can be executed by the setup.py script. This way we have a single
canonical place defining the version number.