zephyr: CONFIG_PICOLIBC + sparse = zephyr/posix/sys/stat.h:40:11: error: unable to open 'sys/_timespec.h'

Describe the bug

CONFIG_PICOLIBC is currently incompatible with sparse due to some .h files complexities.

EDIT October 2nd with newer, simpler, SOF-free reproduction

# Compiles and provides all sparse warnings
west build -b intel_adsp_cavs25  samples/hello_world -p -- \
 -DCONFIG_MINIMAL_LIBC=y -DZEPHYR_SCA_VARIANT=sparse

# Does not compile and can't provide some sparse warnings
west build -b intel_adsp_cavs25  samples/hello_world -p -- \
 -DCONFIG_PICOLIBC=y -DZEPHYR_SCA_VARIANT=sparse 



Slower, -j1 version that does not bury the relevant error:

west build -b intel_adsp_cavs25  samples/hello_world -p -- \
 -DCONFIG_PICOLIBC=y  -DZEPHYR_SCA_VARIANT=sparse

ninja -j1 -C build

Building C object zephyr/lib/libc/picolibc/CMakeFiles/lib__libc__picolibc.dir/libc-hooks.c.obj
zephyr/lib/libc/picolibc/libc-hooks.c: note: in included file:
zephyr/include/zephyr/posix/sys/stat.h:40:11: error: unable to open 'sys/_timespec.h'

OLDER, initial and more complex reproduction that requires SOF. Kept here for completeness, you can probably skip it.

Commit f0daf904bb0202c9247 switched CONFIG_PICOLIBC on by default. This broke the “sparse” analyzer used in the SOF project:

https://github.com/thesofproject/sof/actions/runs/6247162197/job/16959223474?pr=8235

/zep_workspace/zephyr/lib/os/printk.c:123:33: error: undefined identifier 'FDEV_SETUP_STREAM'
/zep_workspace/zephyr/lib/os/printk.c:144:32: error: undefined identifier 'FDEV_SETUP_STREAM'
/zep_workspace/zephyr/lib/os/printk.c:144:49: error: invalid initializer
/zep_workspace/zephyr/include/zephyr/posix/sys/stat.h:40:11: error: unable to open 'sys/_timespec.h'

Note this is not just a sparse warning or false positive: compilation with sparse actually FAILS, it cannot even complete.

To Reproduce

Detailed steps at


Expected behavior

Sparse can still sparse.

Impact

Broken SOF CI

Logs and console output

Environment (please complete the following information):

Github runner Ubuntu 22.04 LTS

Zephyr CI image with Zephyr SDK + https://github.com/marc-hb/sparse/commit/3848a76ba49f336

zephyr commit 341590545ac8 and SOF commit 75337b41eb51)

Additional context

These two workarounds were tested successfully:

  • git revert f0daf904bb0202c9247

  • CONFIG_MINIMAL_LIBC=y as in ~/SOF/sof/scripts/xtensa-build-zephyr.py -p mtl --cmake-args=-DZEPHYR_SCA_VARIANT=sparse --cmake-args=-DCONFIG_LOG_USE_VLA=n --cmake-args=-DCONFIG_MINIMAL_LIBC=y

About this issue

  • Original URL
  • State: closed
  • Created 9 months ago
  • Comments: 18

Commits related to this issue

Most upvoted comments

It works with newlib nano because newlib nano uses almost identical headers, so sparse ends up using the regular newlib headers. With picolibc, we really need the picolibc headers instead. When using sparse and the Zephyr SDK, we could probably compute the required include path:

$ ls $(arm-zephyr-eabi-gcc -print-search-dirs | grep '^install' | sed -e 's/^install: //' -e 's;$;../../../../picolibc/include;')
alloca.h  assert.h    ctype.h	envlock.h   fenv.h     iconv.h	   limits.h  memory.h	 pwd.h	   search.h    ssp	      string.h	  termios.h  utime.h
_ansi.h   bits	      devctl.h	envz.h	    fnmatch.h  ieeefp.h    locale.h  newlib.h	 regdef.h  semihost.h  stdint.h       strings.h   threads.h  utmp.h
argz.h	  byteswap.h  dirent.h	errno.h     getopt.h   inttypes.h  machine   paths.h	 regex.h   setjmp.h    stdio-bufio.h  sys	  time.h     wchar.h
ar.h	  complex.h   elf.h	fastmath.h  glob.h     langinfo.h  malloc.h  picolibc.h  rpc	   signal.h    stdio.h	      _syslist.h  unctrl.h   wctype.h
arpa	  cpio.h      endian.h	fcntl.h     grp.h      libgen.h    math.h    picotls.h	 sched.h   spawn.h     stdlib.h       tar.h	  unistd.h   wordexp.h

. @tejlmand do you want to take another look?

It’s much easier now to debug now that sparse has just been fixed and tls.c does not trigger an infinite loop anymore,

Great, then it sounds like there is hope. Will be on my todo list to be looked at after collab-hwm work.

If no one can help then SOF will have to choose between sparse and PICOLIBC and we’ll close this as won’t fix.

I don’t think this should be closed, as it does seem to be something we should fix. Though I wonder what makes picolibc so different from newlib nano that sets -specs=nano.specs and still works with SOF.

Yup, if sparse isn’t parsing the .specs file to pull in the picolibc header path, it’s not going to work very well. If you know you’re using the Zephyr SDK, you can probably hard-code the picolibc header path for sparse to use. Otherwise, figuring out where the headers are will require digging through whatever toolchain is in use.