#61784 closed defect (fixed)
pv is broken in Apple Silicon
Reported by: | hpux735 (William Dillon) | Owned by: | eborisch (Eric A. Borisch) |
---|---|---|---|
Priority: | Normal | Milestone: | |
Component: | ports | Version: | 2.6.4 |
Keywords: | bigsur, arm64, upstream | Cc: | |
Port: | pv |
Description
There is a build failure in CI (and my local machine) for pv related to stat64's deprecation. I was able to fix it locally, and it's fairly straight-forward, though it's hackish. The root of the problem is that autoconf is able to determine that the stat64 function exists, and therefore thinks that the structure exists, and doesn't include a set of defines that make it OK. I was able to edit config.h to clear the HAVE_STAT64 flag and the program compiled. I have a message out to the pv author. I'm not quite competent in autotools, and I'm not sure what the right way to fix it is, but it appears that the Portfile already has a patch to deal with stat64, so maybe that could be extended without changing upstream?
% diff fixed/config.h broken/config.h 21a22 > #define HAVE_STAT64 1
Change History (6)
comment:1 Changed 4 years ago by jmroot (Joshua Root)
Owner: | set to eborisch |
---|---|
Status: | new → assigned |
comment:2 Changed 4 years ago by mhberger
comment:3 Changed 4 years ago by kencu (Ken)
there's no log or config.log here, so we can't really say what might be going on.
It looks like your PR just removes the flag; although that might well work on one system to fix a build, it doesn't sound like the proper fix, and seems likely to break builds elsewhere...
comment:4 Changed 4 years ago by mhberger
I have done a bit of digging and have come up with something, but not necessarily the ideal soluton.
Basically autoconf takes autoconf/configure.in
and creates configure
, which
then tests for availability of certain functions and then creates #defines
indicating availability of certain functions.
e.g. the autoconf function AC_CHECK_FUNCS(stat64)
generates bash code
in configure which tests for availability of stat64 and if function
is available writes #define HAVE_STAT64 1
.
This code does this by creating a C program conftest.c
and then compiles,
links and runs it.
This C program does not pick up the absence of the symbol at compile time, but
only at link time. i.e. by defining a char stat64 ();
, a compile only will
not fail with an unknown symbol.
See the code example 1 below and try the following on either a Silicon or Intel Mac.
Test 1 – using Joe symbol
Change all occurrences of stat64
to Joe
and compile without linking by
using gcc -S sample.c
. This will report no errors. This is because we have
char Joe ();
.
However if we compile and link gcc sample.c -o sample
, it fails with a
linking error because it cannot find symbol Joe
at link time.
Test 2 – using stat64 symbol
Try the same two tests using stat64
rather than Joe
.
Both the compile only and compile/link will work on both Silicon and Intel.
The compile works because we have a char stat64 ();
.
On the both systems tested, the link works because stat64
is defined as a
symbol in /usr/lib/dyld
which can be seen using
xxd /usr/lib/dyld | grep stat64
In other words, the gcc conftest.c
test will always return true if the symbol
it is testing for can be resolved at link time.
How does this affect the pv port?
The pv
port uses and needs stat64.
The code in the pv include ifndef HAVE_STAT64
does not actually evaluate to
true, so the redefinition of stat64
to stat
does not happen here.
On Intel Macs, the stat64
is not redefined to stat
by standard Apple
includes, but compiles with deprecation warnings, and still links and runs.
On the Silicon Mac, the stat64
is not redefined to stat
by
standard Apple includes, so compiling pv
code generates a compile
warning.
This is demonstrated by compiling, linking and running code example 2.
So to get pv
to build for Silicon, we have to explicitly add a set of defines
for this that will run on Silicon and not on Intel i.e. check for __arm64__
.
# if __arm64__ # define stat64 stat # define fstat64 fstat # define lstat64 lstat # endif
Example 1 – Test code generated by configure
/* confdefs.h */ #define PACKAGE_NAME "" #define PACKAGE_TARNAME "" #define PACKAGE_VERSION "" #define PACKAGE_STRING "" #define PACKAGE_BUGREPORT "" #define PACKAGE_URL "" /* end confdefs.h. */ /* Define stat64 to an innocuous variant, in case <limits.h> declares stat64. For example, HP-UX 11i <limits.h> declares gettimeofday. */ #define stat64 innocuous_stat64 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char stat64 (); below. Prefer <limits.h> to <assert.h> if __STDC__ is defined, since <limits.h> exists even on freestanding compilers. */ #ifdef __STDC__ # include <limits.h> #else # include <assert.h> #endif #undef stat64 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char stat64 (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_stat64 || defined __stub___stat64 choke me #endif int main () { return stat64 (); ; return 0; }
Example 2 – Simple program showing use of stat64
#include <sys/types.h> #include <sys/stat.h> #include <stdio.h> // If following block is uncommented, program compiles, links and runs on Intel // (with deprecation warnings) and Silicon. // On Intel examining the built file `otool -LIV` shows `stat64` being used. // On Silicon examining the built file `otool -LIV` shows `stat` being used. // If following block is commented out (add leading //), then it compiles, links // and runs on Intel (with deprecation warnings) but fails to compile on Silicon // On Intel examining the built file `otool -LIV` shows `stat64` being used. #if __arm64__ #define stat64 stat #endif int main() { struct stat64 info; if (stat64("/", &info) != 0) perror("stat() error"); else { puts("stat() returned the following information about root f/s:"); printf(" inode: %d\n", (int) info.st_ino); printf(" dev id: %d\n", (int) info.st_dev); printf(" mode: %08x\n", info.st_mode); printf(" links: %d\n", info.st_nlink); printf(" uid: %d\n", (int) info.st_uid); printf(" gid: %d\n", (int) info.st_gid); } }
comment:5 Changed 4 years ago by mhberger <21727+mhberger@…>
Resolution: | → fixed |
---|---|
Status: | assigned → closed |
comment:6 Changed 4 years ago by ryandesign (Ryan Carsten Schmidt)
This change is not correct for the universal variant. The port already uses the muniversal portgroup, and the change should be redesigned with that in mind.
Hi, I have had a go at a fix and have created a pull request
https://github.com/macports/macports-ports/pull/9800