Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions builder/frameworks/arduino.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,13 @@ def _overlay_current(d):
os.symlink(join(_API_DIR, name), join(API_DIR, name))

# Detect libgpiod via pkg-config; fall back gracefully if pkg-config is absent.
# Honor a caller-supplied $PKG_CONFIG so cross builds resolve libgpiod against
# the target sysroot rather than the build host (otherwise the simulated GPIO/I2C
# drivers get compiled in and the daemon can't drive real hardware).
_pkg_config = os.environ.get("PKG_CONFIG", "pkg-config")
try:
has_libgpiod = subprocess.call(
["pkg-config", "--exists", "libgpiod"],
[_pkg_config, "--exists", "libgpiod"],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
) == 0
Expand All @@ -57,7 +61,7 @@ def _overlay_current(d):

if has_libgpiod:
cppdefines.append("ARDULINUX_HARDWARE")
raw = subprocess.check_output(["pkg-config", "--cflags", "libgpiod"]).decode().split()
raw = subprocess.check_output([_pkg_config, "--cflags", "libgpiod"]).decode().split()
cpppath += [f[2:] for f in raw if f.startswith("-I")]

env.Append(CPPPATH=cpppath, CPPDEFINES=cppdefines)
Expand Down
20 changes: 20 additions & 0 deletions builder/main.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,28 @@
import os
from os.path import basename, join
from SCons.Script import AlwaysBuild, Default, DefaultEnvironment

env = DefaultEnvironment()

# Honor a caller-supplied cross toolchain from the environment so ArduLinux can
# be built by external build systems (OpenWRT/buildroot, Yocto, Debian rules)
# that provide their own compiler and sysroot. This runs before the framework
# script (main.py -> BuildProgram -> ProcessProgramDeps -> BuildFrameworks ->
# arduino.py), so the override reaches the core/framework objects as well as the
# application's. Each variable is optional; when unset, PlatformIO's native
# gcc/g++ defaults are kept, so ordinary host builds are unaffected. Compiler
# *flags* are intentionally left to the caller (e.g. via PLATFORMIO_BUILD_FLAGS)
# rather than parsed here.
for _scons_var, _env_var in (
("CC", "TARGET_CC"),
("CXX", "TARGET_CXX"),
("AR", "TARGET_AR"),
("RANLIB", "TARGET_RANLIB"),
):
_tool = os.environ.get(_env_var)
if _tool:
env.Replace(**{_scons_var: _tool})

# Allow the application to override the output binary name.
# Set board_build.progname in platformio.ini to change the default "program".
progname = env.BoardConfig().get("build.progname", "")
Expand Down
20 changes: 20 additions & 0 deletions cores/ardulinux/linux/gpio/LinuxGPIOPin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,16 @@ gpiod_line *LinuxGPIOPin::getLine(const char *chipLabel, const char *linuxPinNam
gpiod_line_settings_free(settings);
gpiod_chip_close(chip);
chip = NULL; // prevent double-close in ~LinuxGPIOPin()
// gpiod_chip_request_lines() returns NULL when the line cannot be acquired
// (e.g. already claimed by another process or a kernel driver). Fail loudly
// here instead of returning NULL and asserting later in a reconfigure call.
if (!line) {
char msg[128];
snprintf(msg, sizeof(msg),
"Error, cannot acquire GPIO line '%s' on %s (already in use?)",
linuxPinName ? linuxPinName : "?", chipLabel ? chipLabel : "?");
throw std::invalid_argument(msg);
}
return line;
#else
auto line = gpiod_chip_find_line(chip, linuxPinName);
Expand Down Expand Up @@ -240,6 +250,16 @@ gpiod_line *LinuxGPIOPin::getLine(const char *chipLabel, const int linuxPinNum)
gpiod_line_settings_free(settings);
gpiod_chip_close(chip);
chip = NULL; // prevent double-close in ~LinuxGPIOPin()
// gpiod_chip_request_lines() returns NULL when the line cannot be acquired
// (e.g. already claimed by another process or a kernel driver). Fail loudly
// here instead of returning NULL and asserting later in a reconfigure call.
if (!line) {
char msg[128];
snprintf(msg, sizeof(msg),
"Error, cannot acquire GPIO line %d on %s (already in use?)",
linuxPinNum, chipLabel ? chipLabel : "?");
throw std::invalid_argument(msg);
}
return line;
#else
auto line = gpiod_chip_get_line(chip, linuxPinNum);
Expand Down