castvoid / xserve-frontpanel

A project to re-implement the daemon controlling the Xserve front panel CPU activity LED
MIT License
24 stars 4 forks source link

Compiling for Linux #8

Open osxster opened 4 years ago

osxster commented 4 years ago

I was curious if there is a way to compile this for Linux. I'd like to use this on an ESXi host, however ESXi doesn't have a compiler and thus I am trying to get this to compile on CentOS or BSD instead to see if it can be copied over to ESXi.

Below I am trying with CentOS 8.1, I am able to get this to get a lot of the way through, but it fails a trying to find mach/mach_host.h. See below:

[root@localhost xserve-frontpanel-master]# cmake . && make -- Configuring done -- Generating done -- Build files have been written to: /home/HOME/xserve-frontpanel-master [ 33%] Building C object CMakeFiles/hwmond.dir/cpu_usage.c.o In file included from /home/HOME/xserve-frontpanel-master/cpu_usage.c:1: /home/HOME/xserve-frontpanel-master/cpu_usage.h:3:2: warning: #import is a deprecated GCC extension [-Wdeprecated]

import

^~ /home/HOME/xserve-frontpanel-master/cpu_usage.c:5:10: fatal error: mach/mach_host.h: No such file or directory

include <mach/mach_host.h>

      ^~~~~~~~~~~~~~~~~~

compilation terminated. make[2]: [CMakeFiles/hwmond.dir/build.make:76: CMakeFiles/hwmond.dir/cpu_usage.c.o] Error 1 make[1]: [CMakeFiles/Makefile2:68: CMakeFiles/hwmond.dir/all] Error 2 make: *** [Makefile:84: all] Error 2

It is failing because it is looking for Mach Kernel files which is the Kernel used by MacOS. Is there a way to update this to use Kernel files from Linux? I'd love go to see this work, any help would be greatly appreciated.

ryandesign commented 3 years ago

ESXi can run some Linux ELF binaries but ESXi is not Linux. (ESX was, but ESXi isn't.) I already filed #4 for compiling for ESXi so this new ticket could be about compiling for Linux per your title.

All the Mach-related variables and functions in the code are specific to operating systems like macOS/Darwin that use the Mach microkernel and will need to be made conditional on that (i.e. #ifdef __MACH__). Alternative implementations will need to be created for any other operating systems.

Everything I've found about how to get CPU core usage on Linux says to parse the first few lines of the contents of /proc/stat, for example this programming question and also the source code of unixtop. I was hoping there would be an actual operating system function that you would call to get this information like there is in Mach, but apparently there is not.

ESXi has /proc but does not have /proc/stat so this method won't work there. I'll discuss what will work on ESXi in #4.

ryandesign commented 3 years ago

I was hoping there would be an actual operating system function that you would call to get this information like there is in Mach

Ah, of course the function in question can be found by looking at the source code for the show_stat function in the Linux kernel. Perhaps running just the functions to get the specific CPU info we need is more efficient than having the kernel generate the entire page of info and then parsing it.

I won't link to that code because of the licensing quandry: like the rest of Linux that function is licensed GPL, while this project is licensed MIT, so we could not copy parts of their code into this project without it becoming a derivative work and transforming it into a GPL project. I've looked at the show_stat code so I'm tainted and couldn't write the new code. But I could describe what needs to be done, and mention which kernel header contains the function definitions and structs that would need to be used, and someone else could create a clean room implementation from my description.

We could just go with parsing /proc/stat for now and leave calling the kernel functions directly as an optimization for later.

ryandesign commented 3 years ago

I've installed Linux, figured out how to use X11 forwarding, figured out how to add some code to CMakeLists.txt, separated the Mach-specific code into another file, made a different file for Linux which just uses random numbers so far, figured out how to configure udev to allow write access to the front panel controller, and now I'm stuck at:

$ build/hwmond
[timestamp] [threadID] facility level [function call] <message>
--------------------------------------------------------------------------------
[ 0.003232] [00000e2b] libusb: debug [libusb_get_device_list]
[ 0.003267] [00000e2b] libusb: debug [libusb_get_device_descriptor]
[ 0.003276] [00000e2b] libusb: debug [libusb_get_device_descriptor]
[ 0.003284] [00000e2b] libusb: debug [libusb_open] open 2.5
[ 0.003320] [00000e2b] libusb: debug [usbi_add_pollfd] add fd 9 events 4
[ 0.003332] [00000e2b] libusb: debug [libusb_set_configuration] configuration 0
[ 0.474419] [00000e2b] libusb: debug [libusb_get_config_descriptor] index 0
[ 0.474514] [00000e2b] libusb: debug [libusb_claim_interface] interface 0
Couldn't claim interface: -5
[ 0.474560] [00000e2b] libusb: debug [libusb_close]
[ 0.474567] [00000e2b] libusb: debug [usbi_remove_pollfd] remove fd 9

-5 is LIBUSB_ERROR_NOT_FOUND (and I'll fix the code to use libusb_error_name so that it prints the name instead of the number). API documentation says this happens when the interface does not exist, but it seems like the preceding code has already verified that it does exist, and of course it works as is on macOS.

I found a suggestion that there could be a kernel driver attached to the device, and that one should use libusb_kernel_driver_active to check and if so call libusb_detach_kernel_driver to detach it, and I wrote code to do that, but that didn't change it. I'll investigate more tomorrow.

newperson1746 commented 3 years ago

Hi! I tried to compile for Linux earlier but failed and didn't think about filing an issue. I have an Xserve2,1 on 5.11.0 so I am also happy to test (and be in the loop)

One thing about the GPL "taint": couldn't we do an FFmpeg and simply warn that compiling with the GPL link makes the binary nondistributable or under the GPL license or something like that? Simply adding an #ifdef LINUX does not taint builds unless it actually is compiled for Linux, and even then it does not taint the whole project, merely the binary-- Or so I thought?

ryandesign commented 3 years ago

It's not my project of course but I personally favor non-GNU licenses and wouldn't want to introduce the licensing complications at this point. If the owner of the project wants to change its license to GPL that's up to them. But I think we'll be fine to just read /proc/stat for Linux to start with and can optimize later if needed. I'm not to the point of writing that code yet; I have some more elementary things to become accustomed to on Linux first, since I'm a Mac guy and haven't used Linux much.

ryandesign commented 3 years ago

I now have random LEDs working in Ubuntu Server 20.04 and ESXi 6.0.0. Next step will be to implement real CPU activity data capturing for Linux and then for ESXi.

bobbyl140 commented 2 years ago

Don't know if this project is still alive, but I recently got CentOS Linux installed on my old Xserve and I am having trouble getting this to work. I installed libusb and ran cmake ., but make fails with a few errors. I was able to get it working fine on macOS 10.13 before, but it seems to be finicky on CentOS. I have tried both this repo and the one forked by @ryandesign, both to no avail. I am not knowledgable with C. Does anyone here have any thoughts? Thank you.

The make output is:

[ 25%] Building C object CMakeFiles/hwmond.dir/cpu_usage.c.o
[ 50%] Linking C executable hwmond
CMakeFiles/hwmond.dir/cpu_usage.c.o: In function `get_usage_by_core':
cpu_usage.c:(.text+0x20): undefined reference to `fetch_ticks_by_core'
CMakeFiles/hwmond.dir/cpu_usage.c.o: In function `cpu_usage_setup':
cpu_usage.c:(.text+0x325): undefined reference to `get_num_packages'
cpu_usage.c:(.text+0x343): undefined reference to `fetch_ticks_by_core'
collect2: error: ld returned 1 exit status
make[2]: *** [hwmond] Error 1
make[1]: *** [CMakeFiles/hwmond.dir/all] Error 2
make: *** [all] Error 2