refactor: migrate MICRO_PIP to fine-grained feature flags

Replace monolithic MICRO_PIP/PIP_MICRO with granular flags:

Feature flags (CMake options + platform auto-detection):
- PIP_NO_FILESYSTEM, PIP_NO_THREADS, PIP_NO_SOCKET
- PIP_NO_PROCESS, PIP_NO_DYNLIB, PIP_NO_FFT, PIP_NO_SERIAL

Embedded optimization flag:
- PIP_EMBEDDED (auto-set for Pico SDK and FreeRTOS)
  Controls buffer sizes, time stubs, terminal fallback, init stubs

Platform blocks in CMakeLists.txt:
- Pico SDK: auto-disables FS, PROCESS, DYNLIB, FFT, SERIAL;
  conditionally disables THREADS (no FreeRTOS) and SOCKET (no LWIP)
- FreeRTOS: auto-disables FS, PROCESS, DYNLIB, FFT, SERIAL;
  conditionally disables SOCKET (no LWIP)
- Android: auto-disables PROCESS, DYNLIB, FFT

Updated 96 files across libs/, utils/, tests/, and CMakeLists.txt.
Builds verified for Linux (547 tests pass) and Pico SDK (100%).
Removed all MICRO_PIP and PIP_MICRO references (0 remaining).
This commit is contained in:
2026-08-11 14:34:59 +03:00
parent 87c53d45a4
commit 4d8b743075
97 changed files with 1555 additions and 914 deletions
+74 -70
View File
@@ -2,27 +2,29 @@
#include "piliterals_string.h"
#include "piliterals_time.h"
#ifndef WINDOWS
# include "pidir.h"
# include "pifile.h"
# include "piiostream.h"
# ifdef LINUX
# include <fcntl.h>
# include <linux/input-event-codes.h>
# include <linux/input.h>
# include <sys/ioctl.h>
# include <sys/time.h>
# include <unistd.h>
# else
#ifndef PIP_NO_THREADS
# ifndef WINDOWS
# include "pidir.h"
# include "pifile.h"
# include "piiostream.h"
# ifdef LINUX
# include <fcntl.h>
# include <linux/input-event-codes.h>
# include <linux/input.h>
# include <sys/ioctl.h>
# include <sys/time.h>
# include <unistd.h>
# else
// Stubs for embedded/non-Linux builds
# define EV_SYN 0
# define EV_KEY 1
# define EV_REL 2
# define EV_ABS 3
# define EVIOCGABS(_v) 0
# endif
#else
# define EV_SYN 0
# define EV_KEY 1
# define EV_REL 2
# define EV_ABS 3
# define EVIOCGABS(_v) 0
# endif
# else
// clang-format off
# undef _WIN32_WINNT
# define _WIN32_WINNT 0x0600
@@ -32,7 +34,7 @@ extern "C" {
# include <hidsdi.h>
}
// clang-format on
#endif
# endif
bool PIHIDeviceInfo::match(const PIString & str) const {
@@ -79,14 +81,14 @@ PICout operator<<(PICout s, const PIHIDeviceInfo & v) {
PRIVATE_DEFINITION_START(PIHIDevice)
#ifndef WINDOWS
# ifndef WINDOWS
PIFile file;
bool is_js = false;
#else
# else
PIByteArray buffer;
HANDLE deviceHandle = nullptr;
PHIDP_PREPARSED_DATA preparsed = nullptr;
#endif
# endif
PRIVATE_DEFINITION_END(PIHIDevice)
@@ -95,11 +97,11 @@ PIHIDevice::~PIHIDevice() {
}
bool PIHIDevice::isOpened() const {
#ifndef WINDOWS
# ifndef WINDOWS
return PRIVATE->file.isOpened();
#else
# else
return PRIVATE->deviceHandle;
#endif
# endif
}
@@ -110,21 +112,21 @@ bool PIHIDevice::open(const PIHIDeviceInfo & device) {
di = device;
di.prepare();
if (device.isNull()) return false;
#ifndef WINDOWS
# ifndef WINDOWS
if (!PRIVATE->file.open(di.path, PIIODevice::ReadOnly)) {
piCout << "PIHIDevice::open" << di.path << "error:" << errorString();
return false;
}
PRIVATE->is_js = PIFile::FileInfo(di.path).name().startsWith("js"_a);
return true;
#else
# else
PRIVATE->deviceHandle = CreateFileA(di.path.dataAscii(),
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
nullptr,
OPEN_EXISTING,
0,
nullptr);
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
nullptr,
OPEN_EXISTING,
0,
nullptr);
if (PRIVATE->deviceHandle == INVALID_HANDLE_VALUE) {
piCoutObj << "PIHIDevice::open" << di.path << "error:" << errorString();
PRIVATE->deviceHandle = nullptr;
@@ -136,7 +138,7 @@ bool PIHIDevice::open(const PIHIDeviceInfo & device) {
return false;
}
return true;
#endif
# endif
}
@@ -147,9 +149,9 @@ bool PIHIDevice::open() {
void PIHIDevice::close() {
stop();
#ifndef WINDOWS
# ifndef WINDOWS
PRIVATE->file.close();
#else
# else
if (PRIVATE->deviceHandle) {
CloseHandle(PRIVATE->deviceHandle);
PRIVATE->deviceHandle = nullptr;
@@ -158,34 +160,34 @@ void PIHIDevice::close() {
HidD_FreePreparsedData(PRIVATE->preparsed);
PRIVATE->preparsed = nullptr;
}
#endif
# endif
}
void PIHIDevice::start() {
if (!isOpened()) return;
PIThread::start(200_Hz);
#ifndef WINDOWS
#else
#endif
# ifndef WINDOWS
# else
# endif
}
void PIHIDevice::stop() {
PIThread::stop();
#ifdef WINDOWS
# ifdef WINDOWS
if (PRIVATE->deviceHandle) {
CancelIoEx(PRIVATE->deviceHandle, nullptr);
}
#endif
# endif
if (!waitForFinish(1000_ms)) terminate();
}
void PIHIDevice::run() {
Event e;
#ifndef WINDOWS
# pragma pack(push, 1)
# ifndef WINDOWS
# pragma pack(push, 1)
struct input_event {
struct timeval time;
ushort type;
@@ -198,7 +200,7 @@ void PIHIDevice::run() {
uchar type; /* event type */
uchar number; /* axis/button number */
};
# pragma pack(pop)
# pragma pack(pop)
if (PRIVATE->is_js) {
js_event ie;
while (PRIVATE->file.read(&ie, sizeof(ie)) == sizeof(ie)) {
@@ -253,7 +255,7 @@ void PIHIDevice::run() {
if (!ok) continue;
}
}
#else
# else
PRIVATE->buffer.resize(di.input_report_size).fill(0);
DWORD readed = 0;
// piCout << "read" << PRIVATE->deviceHandle << PRIVATE->buffer.size();
@@ -293,7 +295,7 @@ void PIHIDevice::run() {
continue;
}
}
#endif
# endif
auto ait = cur_axes.makeIterator();
e.type = Event::tAxisMove;
@@ -333,7 +335,7 @@ double PIHIDevice::procDeadZone(double in) {
PIVector<PIHIDeviceInfo> PIHIDevice::allDevices(bool try_open) {
PIVector<PIHIDeviceInfo> ret;
#ifndef WINDOWS
# ifndef WINDOWS
auto readFile = [](const PIString & path) {
auto ba = PIFile::readAll(path);
@@ -379,11 +381,11 @@ PIVector<PIHIDeviceInfo> PIHIDevice::allDevices(bool try_open) {
}
/*bool dev_found = false;
for (const auto & d: devs) {
if (d.startsWith("js"_a)) {
dev.path = "/dev/input/"_a + d;
dev_found = true;
break;
}
if (d.startsWith("js"_a)) {
dev.path = "/dev/input/"_a + d;
dev_found = true;
break;
}
}
if (!dev_found) {*/
// search for event<N> dir
@@ -408,7 +410,7 @@ PIVector<PIHIDeviceInfo> PIHIDevice::allDevices(bool try_open) {
ullong bits = readFile(hd_i.path + file).toULLong(16);
// piCout<< PICoutManipulators::Bin << abs;
if (bits > 0) {
#ifdef LINUX
# ifdef LINUX
int fd = ::open(dev.path.dataAscii(), O_RDONLY);
if (fd < 0) {
// piCout << "Warning: can`t open" << dev.path << errorString();
@@ -433,7 +435,7 @@ PIVector<PIHIDeviceInfo> PIHIDevice::allDevices(bool try_open) {
}
}
if (fd >= 0) ::close(fd);
#else
# else
// Stub implementation for non-Linux builds
PIHIDeviceInfo::AxisInfo ai;
ai.is_relative = is_relative;
@@ -445,7 +447,7 @@ PIVector<PIHIDeviceInfo> PIHIDevice::allDevices(bool try_open) {
ret << ai;
}
}
#endif
# endif
}
return ret;
};
@@ -496,7 +498,7 @@ PIVector<PIHIDeviceInfo> PIHIDevice::allDevices(bool try_open) {
}
}
#else
# else
GUID guid;
HidD_GetHidGuid(&guid);
@@ -518,23 +520,23 @@ PIVector<PIHIDeviceInfo> PIHIDevice::allDevices(bool try_open) {
PIScopeExitCall exit_call([&deviceInterfaceDetailData]() { delete[] reinterpret_cast<BYTE *>(deviceInterfaceDetailData); });
deviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
if (!SetupDiGetDeviceInterfaceDetail(deviceInfoSet,
&deviceInterfaceData,
deviceInterfaceDetailData,
requiredSize,
nullptr,
nullptr)) {
&deviceInterfaceData,
deviceInterfaceDetailData,
requiredSize,
nullptr,
nullptr)) {
piCout << "SetupDiGetDeviceInterfaceDetail error:" << errorString();
continue;
}
if (try_open) {
auto test_f = CreateFileA(deviceInterfaceDetailData->DevicePath,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
nullptr,
OPEN_EXISTING,
0,
nullptr);
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
nullptr,
OPEN_EXISTING,
0,
nullptr);
if (test_f == INVALID_HANDLE_VALUE) continue;
CloseHandle(test_f);
}
@@ -657,7 +659,7 @@ PIVector<PIHIDeviceInfo> PIHIDevice::allDevices(bool try_open) {
SetupDiDestroyDeviceInfoList(deviceInfoSet);
#endif
# endif
return ret;
}
@@ -671,3 +673,5 @@ PIHIDeviceInfo PIHIDevice::findDevice(const PIString & name) {
}
return PIHIDeviceInfo();
}
#endif // PIP_NO_THREADS
+3 -1
View File
@@ -169,6 +169,7 @@ PIP_EXPORT PICout operator<<(PICout s, const PIHIDeviceInfo & v);
//! \~english Provides access to HID (Human Interface Device) devices such as game controllers, joysticks, and other input devices.
//! \~russian Предоставляет доступ к HID (Human Interface Device) устройствам, таким как геймконтроллеры, джойстики и другие устройства
//! ввода.
#ifndef PIP_NO_THREADS
class PIP_EXPORT PIHIDevice: public PIThread {
PIOBJECT_SUBCLASS(PIHIDevice, PIThread)
@@ -188,7 +189,7 @@ public:
tNone /** \~english Empty event \~russian Пустое событие */,
tButton /** \~english Button state change \~russian Изменение состояния кнопки */,
tAxisMove /** \~english Axis value change or relative axis delta \~russian Изменение значения оси или дельта относительной оси
*/
*/
,
};
@@ -270,6 +271,7 @@ private:
PIMap<int, int> prev_buttons, cur_buttons;
float dead_zone = 0.f;
};
#endif // PIP_NO_THREADS
#endif
+2 -2
View File
@@ -17,7 +17,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef MICRO_PIP
#ifndef PIP_NO_DYNLIB
# include "pilibrary.h"
@@ -233,4 +233,4 @@ void PILibrary::getLastError() {
# endif
}
#endif // MICRO_PIP
#endif // PIP_NO_DYNLIB
+2 -2
View File
@@ -26,7 +26,7 @@
#ifndef PILIBRARY_H
#define PILIBRARY_H
#ifndef MICRO_PIP
#ifndef PIP_NO_DYNLIB
# include "pistring.h"
@@ -82,5 +82,5 @@ private:
PIString libpath, liberror;
};
#endif // MICRO_PIP
#endif // PIP_NO_DYNLIB
#endif // PILIBRARY_H
+2 -2
View File
@@ -17,7 +17,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef MICRO_PIP
#ifndef PIP_NO_DYNLIB
# include "piplugin.h"
@@ -493,4 +493,4 @@ PIString PIPluginLoader::libExtension() {
}
#endif // MICRO_PIP
#endif // PIP_NO_DYNLIB
+21 -23
View File
@@ -28,7 +28,7 @@
#ifndef PIPLUGIN_H
#define PIPLUGIN_H
#ifndef MICRO_PIP
#ifndef PIP_NO_DYNLIB
# include "pilibrary.h"
# include "pistringlist.h"
@@ -96,30 +96,28 @@
# define __PIP_PLUGIN_STATIC_MERGE_FUNC__ pip_merge_static
# define __PIP_PLUGIN_LOADER_VERSION__ 2
# define PIP_PLUGIN_SET_USER_VERSION(v) \
STATIC_INITIALIZER_BEGIN \
PIPluginInfo * pi = PIPluginInfoStorage::instance()->currentInfo(); \
if (pi) pi->setUserVersion(v); \
STATIC_INITIALIZER_END
# define PIP_PLUGIN_SET_USER_VERSION(v) \
STATIC_INITIALIZER_BEGIN \
PIPluginInfo * pi = PIPluginInfoStorage::instance()->currentInfo(); \
if (pi) pi->setUserVersion(v); \
STATIC_INITIALIZER_END
# define PIP_PLUGIN_ADD_STATIC_SECTION(type, ptr) \
STATIC_INITIALIZER_BEGIN \
PIPluginInfo * pi = PIPluginInfoStorage::instance()->currentInfo(); \
if (pi) pi->setStaticSection(type, ptr); \
STATIC_INITIALIZER_END
# define PIP_PLUGIN_ADD_STATIC_SECTION(type, ptr) \
STATIC_INITIALIZER_BEGIN \
PIPluginInfo * pi = PIPluginInfoStorage::instance()->currentInfo(); \
if (pi) pi->setStaticSection(type, ptr); \
STATIC_INITIALIZER_END
# define PIP_PLUGIN \
extern "C" { \
PIP_PLUGIN_EXPORT int __PIP_PLUGIN_LOADER_VERSION_FUNC__() { \
return __PIP_PLUGIN_LOADER_VERSION__; \
} \
}
# define PIP_PLUGIN \
extern "C" { \
PIP_PLUGIN_EXPORT int __PIP_PLUGIN_LOADER_VERSION_FUNC__() { return __PIP_PLUGIN_LOADER_VERSION__; } \
}
# define PIP_PLUGIN_STATIC_SECTION_MERGE \
extern "C" { \
PIP_PLUGIN_EXPORT void __PIP_PLUGIN_STATIC_MERGE_FUNC__(int type, void * from, void * to); \
} \
void __PIP_PLUGIN_STATIC_MERGE_FUNC__(int type, void * from, void * to)
# define PIP_PLUGIN_STATIC_SECTION_MERGE \
extern "C" { \
PIP_PLUGIN_EXPORT void __PIP_PLUGIN_STATIC_MERGE_FUNC__(int type, void * from, void * to); \
} \
void __PIP_PLUGIN_STATIC_MERGE_FUNC__(int type, void * from, void * to)
# endif
@@ -300,5 +298,5 @@ private:
};
#endif // MICRO_PIP
#endif // PIP_NO_DYNLIB
#endif // PIPLUGIN_H
+2 -2
View File
@@ -18,7 +18,7 @@
*/
#include "pitime.h"
#ifndef MICRO_PIP
#ifndef PIP_NO_PROCESS
# include "piincludes_p.h"
# include "piliterals_bytes.h"
@@ -507,4 +507,4 @@ PIString PIProcess::getEnvironmentVariable(const PIString & variable) {
return PIString();
}
#endif // MICRO_PIP
#endif // PIP_NO_PROCESS
+2 -2
View File
@@ -26,7 +26,7 @@
#ifndef PIPROCESS_H
#define PIPROCESS_H
#ifndef MICRO_PIP
#ifndef PIP_NO_PROCESS
# include "pithread.h"
@@ -258,5 +258,5 @@ private:
std::atomic_bool exec_finished;
};
#endif // MICRO_PIP
#endif // PIP_NO_PROCESS
#endif // PIPROCESS_H
+10
View File
@@ -207,11 +207,19 @@ PIVector<PISystemInfo::MountInfo> PISystemInfo::mountInfo(bool ignore_cache) {
PIString confDir() {
return
#ifdef WINDOWS
# ifndef PIP_NO_FILESYSTEM
PIDir::home().path() + "/AppData/Local"
# else
""
# endif
#elif defined(ANDROID)
""
#else
# ifndef PIP_NO_FILESYSTEM
PIDir::home().path() + "/.config"
# else
""
# endif
#endif
;
}
@@ -234,11 +242,13 @@ PIString PISystemInfo::machineKey() {
PISystemInfo * si = instance();
PIByteArray salt;
PIString conf = confDir() + "/.pip_machine_salt";
#ifndef PIP_NO_FILESYSTEM
if (PIFile::isExists(conf)) salt = PIFile::readAll(conf);
if (salt.size_s() != SALT_SIZE) {
salt = generateSalt();
PIFile::writeAll(conf, salt);
}
#endif
ret = si->OS_name + "_" + si->architecture + "_" + si->hostname + "_" + salt.toHex();
}
return ret;
+4 -4
View File
@@ -19,9 +19,9 @@
#include "pisystemtests.h"
#ifndef MICRO_PIP
#ifndef PIP_NO_FILESYSTEM
# include "piconfig.h"
#endif
#endif // !PIP_NO_FILESYSTEM
namespace PISystemTests {
@@ -35,10 +35,10 @@ PISystemTestReader pisystestreader;
PISystemTests::PISystemTestReader::PISystemTestReader() {
#if !defined(WINDOWS) && !defined(MICRO_PIP)
#if !defined(WINDOWS) && !defined(PIP_NO_FILESYSTEM)
PIConfig conf(PIStringAscii("/etc/pip.conf"), PIIODevice::ReadOnly);
time_resolution_ns = conf.getValue(PIStringAscii("time_resolution_ns"), 1).toLong();
time_elapsed_ns = conf.getValue(PIStringAscii("time_elapsed_ns"), 0).toLong();
usleep_offset_us = conf.getValue(PIStringAscii("usleep_offset_us"), 60).toLong();
#endif
#endif // !WINDOWS && !PIP_NO_FILESYSTEM
}