Opened 5 years ago
Closed 11 months ago
#59992 closed defect (fixed)
ncurses@6.1 : /opt/local/include/unctrl.h:60:63: error: unknown type name 'SCREEN'
Reported by: | kencu (Ken) | Owned by: | jmroot (Joshua Root) |
---|---|---|---|
Priority: | Normal | Milestone: | |
Component: | ports | Version: | |
Keywords: | upstream | Cc: | MarcusCalhoun-Lopez (Marcus Calhoun-Lopez), mascguy (Christopher Nielsen) |
Port: | ncurses |
Description
our ncurses
port is 6.1, and appears to include some new functionality with respect to screen pointers that can cause build errors with software not expecting this.
Most MacOS systems are using ncurses < 6.0, and this can generate errors like this, when building software that calls in the SDK's headers, eg #53155:
In file included from /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk/usr/include/ncurses.h:141: /opt/local/include/unctrl.h:60:63: error: unknown type name 'SCREEN' NCURSES_EXPORT(NCURSES_CONST char *) NCURSES_SP_NAME(unctrl) (SCREEN*, chtype); ^ /opt/local/include/unctrl.h:60:53: error: function cannot return function type 'char *(int *, chtype)' (aka 'char *(int *, unsigned int)') NCURSES_EXPORT(NCURSES_CONST char *) NCURSES_SP_NAME(unctrl) (SCREEN*, chtype); ^ /opt/local/include/unctrl.h:60:54: error: a parameter list without types is only allowed in a function definition NCURSES_EXPORT(NCURSES_CONST char *) NCURSES_SP_NAME(unctrl) (SCREEN*, chtype); ^ 3 errors generated.
I recently ran into this trying to enable the LLVM test suite for libtapi on Darwin, which errors out with that error.
There are many reports of this issue on Google, and they all say to "uninstall MacPorts" or "get rid of that" etc. Google this :
"error: unknown type name 'SCREEN'"
for a number of examples.
It looks like this new SCREEN functionality is optional
Extensions: --disable-ext-funcs disable function-extensions --enable-sp-funcs enable SCREEN-extensions
however, when I tried this in ncurses:
configure.args-append --disable-sp-funcs
it failed due to :
../ncurses/./base/new_pair.c:280:25: error: use of undeclared identifier 'sp' /usr/bin/clang -DHAVE_CONFIG_H -I../ncurses -I. -I../include -D_DARWIN_C_SOURCE -DNDEBUG -pipe -Os -arch x86_64 -arch i386 -no-cpp-precomp --param max-inline-insns-single=1200 -dynamic -c ../ncurses/./base/resizeterm.c -o ../obj_s/resizeterm.o if (_nc_reserve_pairs(sp, pair) == 0) { ^ 1 error generated. make[1]: *** [../obj_s/new_pair.o] Error 1 make[1]: *** Waiting for unfinished jobs....
On a case-by-case basis, you can sometimes block the troublesome MacPorts header like this:
configure.cppflags-append -DNCURSES_UNCTRL_H_incl
but of course that is less than ideal.
I'm not sure if we are finding the new SCREEN functionality useful, but perhaps if not, disabling it for now until all the various software catches up might be useful.
Change History (44)
comment:1 Changed 5 years ago by jmroot (Joshua Root)
comment:2 Changed 5 years ago by kencu (Ken)
This happens in multiple builds, not just handbrake.
I don't fully understand why this is happening, but this post <https://stackoverflow.com/questions/44485899/xcode-unknown-type-name-screen-only-when-building-for-release-in-file-unct> claims to have sorted it out.
comment:3 Changed 5 years ago by jmroot (Joshua Root)
It's managing to include /usr/include/ncurses.h despite -I/opt/local/include being used. The important part seems to be a line you didn't quote,
In file included from <module-includes>:337:
That seems to be an alternate way of finding headers used by Xcode. Again, using the MacPorts ncurses as per our general policy would solve the problem.
comment:4 follow-up: 6 Changed 5 years ago by kencu (Ken)
You seem to have it understood. Do you have some insight into what is the fix?
MacPorts ncurses is installed. CMake is configured as usual. I"m sorry I don't see what to do.
comment:5 Changed 5 years ago by kencu (Ken)
(I just edited our MacPorts' unctrl.h
locally to disable the SCREEN usage, and that works just fine until we sort this out properly).
comment:6 Changed 5 years ago by jmroot (Joshua Root)
Replying to kencu:
MacPorts ncurses is installed. CMake is configured as usual. I"m sorry I don't see what to do.
You're talking about libtapi? I haven't ever seen a log for that, so I don't know what it's even trying to do.
comment:7 Changed 5 years ago by kencu (Ken)
it seems a systemic issue, for which HandBrake and the libtapi tests are examples.
The issue may well be with modules
-- <https://clang.llvm.org/docs/Modules.html> -- although how to fix it is not at present clear to me.
For now, disabling SCREEN manually in unctrl.h
works as a workaround for anyone bitten by this, I guess. I don't know any other fix, other than building our ncurses
port with SCREEN
disabled.
comment:8 Changed 5 years ago by jmroot (Joshua Root)
The fix is to include /opt/local/include/ncurses.h not /usr/include/ncurses.h. I don't know how to say that any more plainly.
comment:9 follow-up: 12 Changed 5 years ago by kencu (Ken)
it is being included by the module map, over which we have no control. What you suggest is not possible, AFAICT.
comment:10 Changed 5 years ago by jmroot (Joshua Root)
If you're having trouble understanding the issue, I'll try to explain it in more generic terms. Suppose you have a pair of headers foo.h and bar.h, and they exist in both /usr/include and /usr/local/include. The pair in each location is designed to work together, but using one header from one location and the other header from the other location won't work for whatever reason (the possibilities are endless really).
Now further suppose each foo.h contains a line #include <bar.h>
. Now consider a C program baz.c that starts like this:
#include <foo.h> ...
When compiled, the preprocessor will looks for foo.h in its search paths. /usr/local/include comes first, so it will use /usr/local/include/foo.h. While processing that file, it will see #include <bar.h>
, and go through the same process to find that file, again using the one in /usr/local/include. Everything works fine.
But consider if you change baz.c to this:
#include </usr/include/foo.h> ...
Now the preprocessor will load /usr/include/foo.h because it is specified with an absolute path. While processing foo.h, it will again see #include <bar.h>
, and find bar.h in /usr/local/include because that location is first in the list. Oops, the headers aren't compatible and the program breaks.
comment:11 Changed 5 years ago by kencu (Ken)
homebrew does not seem to have this issue <https://github.com/Homebrew/homebrew-core/blob/master/Formula/ncurses.rb>, and appears to make no special compensations for it.
I could guess that is because it installs ncurses.h
into /usr/local/include
and so it is found automatically by the module map there ahead of /usr/include
, but I'm not certain about that.
comment:12 follow-up: 13 Changed 5 years ago by jmroot (Joshua Root)
Replying to kencu:
it is being included by the module map, over which we have no control. What you suggest is not possible, AFAICT.
If the module map doesn't understand that /usr/include/ncurses.h needs to include /usr/include/unctrl.h then it's pretty broken.
How do you know Homebrew doesn't have the issue? Have they built the libtapi test suite?
comment:13 Changed 5 years ago by kencu (Ken)
Replying to jmroot:
If the module map doesn't understand that /usr/include/ncurses.h needs to include /usr/include/unctrl.h then it's pretty broken.
Yes, I guess so. I wish I knew what Jeremy knows -- where does this module map come from? Can we regenerate it? Disable it? Edit it to point to our ncurses.h?
I think we can set ${prefix}/include
to be a system include path ahead of /usr/include
to fix this, maybe... PITA, though... each build system does this differently...
How do you know Homebrew doesn't have the issue? Have they built the libtapi test suite?
Just a guess. The general solution for this error on the internet / SourceForge / etc is to uninstall MacPorts and use homebrew instead, so that's one clue. Also googlng this error shows only MacPorts errors with it. Homebrew does have a functioning HandBrake formulae -- but things have changed with the HandBrake build so can't compare, really.
comment:14 Changed 5 years ago by kencu (Ken)
I continue to be completely unable to get past this error without hand-editing unctrl.h
to disable the SCREEN
usage that triggers the error.
No combination of trickery seems to fix it.
Module information is here <https://clang.llvm.org/docs/Modules.html#using-modules>. I presume the module map that is causing the issue is right in the CoreFoundation Framework, but my knowledge of where this is going wrong is apparently incomplete as I can't (so far) fix it.
comment:15 Changed 5 years ago by kencu (Ken)
This same issue now prevents building a current clang-devel
, due to the same error with modules once again.
clang refuses to configure without module support, which cannot be made to work (so far, by me at least) with this version of ncurses
enabling SCREEN.
This is with the current llvm / clang checkout from GitHub, using Apple's build scripts. So ... I'm open to ideas.
comment:16 Changed 5 years ago by kencu (Ken)
OK -- so is there any fix or workaround to our ncurses
port that would be considered acceptable?
I don't think it's realistic to ask Apple to fix their modules
implementation, whatever is wrong with it that causes it to pull in our unctrl.h
header instead of the one in the SDK. Leaving this broken can't really be a great plan.
in uncntrl.h
there is
#include <curses.h> #undef unctrl NCURSES_EXPORT(NCURSES_CONST char *) unctrl (chtype); #if 1 NCURSES_EXPORT(NCURSES_CONST char *) NCURSES_SP_NAME(unctrl) (SCREEN*, chtype); #endif
I could patch in an extra guard in there to exclude Apple's curses 5.x curses.h from pulling in the SCREEN definition, like this:
#include <curses.h> #undef unctrl NCURSES_EXPORT(NCURSES_CONST char *) unctrl (chtype); #if NCURSES_VERSION_MAJOR > 5 #if 1 NCURSES_EXPORT(NCURSES_CONST char *) NCURSES_SP_NAME(unctrl) (SCREEN*, chtype); #endif #endif
And then I think we'd change nothing in our port, but we'd no longer be broken with Apple's modules. I have confirmed on my systems here that fixes the problem with modules by blocking our header from defining SCREEN.
Otherwise I guess we get Jeremy or some similar Apple engineer in here to tell us how to make MacPorts' ncurses
port play nice with Apple's clang modules implementation.
As mentioned above, the general fix on the internet / stack exchange, etc is to just "uninstall MacPorts".
comment:17 Changed 5 years ago by kencu (Ken)
Here is the clang documentation on module support and search paths <https://clang.llvm.org/docs/Modules.html>
comment:18 Changed 5 years ago by jmroot (Joshua Root)
There is no bug in ncurses here. I think you need to work with the LLVM developers to find a solution. This can't possibly be working as intended on the LLVM side.
comment:19 Changed 5 years ago by kencu (Ken)
I guess we'll copy Jeremy in on it and let him resolve it. Modules support will have to be disabled on clang until MacPorts / llvm come to an agreement about it.
Modules are part of the c++20 standard, but not much software is calling for it yet (other than Apple's software).
Let me know if you change your mind about ncurses -- it's a 10 second, no-harm-no-foul workaround. Not a pure fix, but a workaround.
comment:20 Changed 5 years ago by MarcusCalhoun-Lopez (Marcus Calhoun-Lopez)
Most of my research on this issue has focused on cargo since that ticket was assigned to me.
I hope the ideas are generally applicable.
Minimal reproducible error is
echo "#import <Foundation/Foundation.h>" | env CPATH=/opt/local/include clang -xobjective-c -c -fmodules -v -o test.o -
The odd part is that this is not an error
echo "#import <Foundation/Foundation.h>" | clang -xobjective-c -c -fmodules -v -o test.o - echo "#import <Foundation/Foundation.h>" | env CPATH=/opt/local/include clang -xobjective-c -c -fmodules -v -o test.o -
The reason seems to be the flag -fmodules-cache-path=...
.
echo "#import <Foundation/Foundation.h>" | clang -xobjective-c -c -fmodules -v -o test.o -
generates a bunch of precompiled header files.
Once generated,
echo "#import <Foundation/Foundation.h>" | env CPATH=/opt/local/include clang -xobjective-c -c -fmodules -v -o test.o -
uses them with no issues.
If the cache files are deleted,
echo "#import <Foundation/Foundation.h>" | env CPATH=/opt/local/include clang -xobjective-c -c -fmodules -v -o test.o -
goes back to generating an error.
It seems that the problem is fundamentally that CPATH=${prefix}/include
prevents the proper generation of precompiled header files.
The new port in #60150 actually seems to build with the simple addition of
compiler.cpath
Removing -fmodules
also prevents the error
echo "#import <Foundation/Foundation.h>" | env CPATH=/opt/local/include clang -xobjective-c -c -v -o test.o -
I have not yet experimented with C++20 modules to see if similar issues arise.
comment:21 Changed 5 years ago by MarcusCalhoun-Lopez (Marcus Calhoun-Lopez)
Cc: | MarcusCalhoun-Lopez added |
---|
comment:22 Changed 5 years ago by kencu (Ken)
FYI I believe this is being looked into upstream at Apple, but I don't know of a radar, etc, for it, if there is one
comment:23 follow-up: 30 Changed 5 years ago by kencu (Ken)
essentially, when clang is using modules, but a CPATH is set, instead of honouring the CPATH it first looks at the cached module map which sends it into the SDK, but then does honour the CPATH for further includes.
This situation is non-viable. Disabling modules of course works. disabling CPATH disables MacPorts, basically.
Some clang trickery to regenerate the module map automatically if CPATH is set would appear to be needed.
This can't be the only time this is noticed, but MacPorts is likely the first place this would show up, running a current clang with non-standard header include paths and setting CPATH.
comment:24 follow-up: 29 Changed 5 years ago by kencu (Ken)
<http://lists.llvm.org/pipermail/cfe-dev/2020-March/065021.html>
let's see what they say...
comment:25 Changed 5 years ago by MarcusCalhoun-Lopez (Marcus Calhoun-Lopez)
Please forgive my ignorance, but where has this issue cropped up?
Just reading through this ticket:
- topgrade
- HandBrake? (other build issues prevent me from testing).
- libtapi? (builds fine for me)
- others?
comment:26 Changed 5 years ago by kencu (Ken)
Anything that uses Xcode clang and modules is currently not functional in MacPorts by ncurses. Modules are a newer feature, so penetrance is evolving.
I manually delete the libtapi tests that use modules, so you wouldn't see it. Proper clang-devel builds now want modules, and fail in MacPorts because of ncurses.
google "error: unknown type name 'SCREEN'" for hits on other projects.
I have tweaked my MacPorts unctrl.h to work around this, as at present that is the only solution I know of that generally works --- it's not a pure fix, I know .
But neither is unsetting CPATH and the library path, or disabling module support, or the parts of projects that require modules. We'll have to go back and undo all those when clang is fixed too, and IMHO those are more impactful than tweaking unctrl.h until Apple figures this out.
Or perhaps we can fix the clang issue -- if we could do that, all this would go away in a proper fashion.
comment:27 Changed 5 years ago by MarcusCalhoun-Lopez (Marcus Calhoun-Lopez)
Just to refine my analysis:
- Minimal reproducible error
echo "#import <sys/types.h>" | env CPATH=/opt/local/include clang -xobjective-c -c -fmodules -v -o test.o -
echo "import Darwin" | env CPATH=/opt/local/include swiftc -v -o test.o -
- The problem happens only during the generation of the module cache.
- Once the cache files are generated (see
-fmodules-cache-path=...
), subsequent compilations work fine. - The specific cache directory seems to depends on quite a few variables.
- MACOSX_DEPLOYMENT_TARGET
- DEVELOPER_DIR
- SDKROOT
-O
- Once the cache files are generated (see
- The problem happens with the reading of
/Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/usr/include/module.modulemap
.module Darwin
has a submoduleexplicit module ncurses
, which has a submoduleexplicit module unctrl
.- ncurses has a circular include dependency.
ncurses.h
includesunctrl.h
unctrl.h
includesncurses.h
- Newer versions of ncurses have changed exactly how these two files interact.
module.modulemap
does not seem to have a mechanism to handle circular dependencies.
Here are some possible solutions/workarounds:
- Patch Clang
- If the circular dependencies are a fundamental issue. there is nothing to be done.
- Any changes would take quite a while (if ever) to reach Xcode clang.
- Almost certainly, Clang upstream help would be required.
- Patch
uncntrl.h
to removeSCREEN
.- We would be removing expected functionality to facilitate the generation of cache files.
- We would forever be responsible for making sure
uncntrl.h
continued to work.
- Patch
uncntrl.h
to minimize the effect of the circular dependency.- It is not clear yet how this could be accomplished.
- We should have to work with ncurses upstream to get any changes merged.
- Generate required cache files before building the port (e.g. during
post-extract
).- I was able to accomplish this with the port topgrade.
- A PortGroup could accomplish this with some effort.
- It is very fragile since the cache directory name is highly dependent on the compiler settings.
- Attempt to get ncurses to work within the modules infrastructure.
- There is a pull request to that effect.
- I am not 100% sure why this works or how fragile it is.
comment:28 Changed 5 years ago by kencu (Ken)
FYI, this is what I did in our unctrl.h
#include <curses.h> #undef unctrl NCURSES_EXPORT(NCURSES_CONST char *) unctrl (chtype); + #if NCURSES_VERSION_MAJOR > 5 #if 1 NCURSES_EXPORT(NCURSES_CONST char *) NCURSES_SP_NAME(unctrl) (SCREEN*, chtype); #endif + #endif
comment:29 Changed 4 years ago by ryandesign (Ryan Carsten Schmidt)
Replying to kencu:
<http://lists.llvm.org/pipermail/cfe-dev/2020-March/065021.html>
let's see what they say...
I see no response.
comment:30 Changed 4 years ago by ryandesign (Ryan Carsten Schmidt)
Replying to kencu:
disabling CPATH disables MacPorts, basically.
I've always considered CPATH and LIBRARY_PATH to be extra sugar to help build systems that weren't doing things quite right. MacPorts existed for a long time before it started setting CPATH and LIBRARY_PATH and worked just fine by using -I and -L flags.
comment:31 Changed 4 years ago by kencu (Ken)
In the case of the specific port Marcus was working on, is was a cargo build, there were no FLAGS being used at all. It was being driven by CPATH and LIBRARY_PATH <https://github.com/macports/macports-ports/pull/6484/commits/0b67f8df23624aa279846dc8279817d8f084091e> and that's why I said that disabling CPATH disabled MacPorts, basically, for that specific instance.
Which is why I considered it to be not a fix for this issue, although it did work around the broken build in that one specific port.
In general, for other kinds of builds, autotools, cmake, etc, then yes, the passing of include flags makes CPATH redundant, and likewise for -L and LIBRARY_PATH and what you say would be accurate for those ports.
comment:32 Changed 4 years ago by MarcusCalhoun-Lopez (Marcus Calhoun-Lopez)
comment:33 Changed 3 years ago by mascguy (Christopher Nielsen)
Cc: | mascguy added |
---|
comment:34 Changed 21 months ago by jmroot (Joshua Root)
Keywords: | upstream added |
---|
This is working its way through the proper channels at Apple (DTS incident). Currently no workaround to offer apart from "don't use -fmodules" (which isn't actually that unreasonable, since modules are just a build speed optimisation after all.)
comment:35 Changed 21 months ago by kencu (Ken)
Anyone encountering this error can use the new port macports-module-map
into which the modules fix has been moved:
[93c93a6b4739d9754fa13b9df3a9677ee91dcbd6/macports-ports]
even if Apple figures out how to fix the SDK to not barf on this issue, we will presumably have to carry this port and it's fix along pretty much forever, as all the SDKs up to the point where it is perhaps fixed someday won't have the fix in it.
comment:36 Changed 20 months ago by jmroot (Joshua Root)
DTS has suggested to try using the __building_module
builtin in our headers. For example, our unctrl.h
would look like:
#if __building_module(Darwin) #include_next <unctrl.h> #else // normal content of file from ncurses 6 #endif
It would be a little more code in practice, e.g. we'd have to first check that the compiler has that builtin.
comment:37 Changed 20 months ago by saagarjha (Saagar Jha)
It seems like you're working on a fix, but I do want to mention that "don't use -fmodules" is not going to work for any of our Swift ports.
comment:38 Changed 19 months ago by p-keller
For info: the #if __building_module(Darwin) #include_next
patch floated my boat. I didn't bother with any checks for availability of the builtin, since my problem was with a standard macOS build in Xcode.
comment:39 Changed 19 months ago by kencu (Ken)
DTS's suggestion is not much of a fix, and also not very broadly compatible.
Marcus' module.map fix is a lot more elegant than what DTS suggested, not that I exactly understand why/how Marcus' fix actually works :>
Neither of these should be needed, but modules remain very new, and I don't think anyone really gets them yet, so "all hacks on board".
comment:40 Changed 11 months ago by jmroot (Joshua Root)
comment:41 Changed 11 months ago by jmroot (Joshua Root)
I'm inclined to close this as "as fixed as it's going to get on our end", unless anyone knows of anything else that we can/should do?
comment:43 Changed 11 months ago by jmroot (Joshua Root)
comment:44 Changed 11 months ago by jmroot (Joshua Root)
Resolution: | → fixed |
---|---|
Status: | assigned → closed |
Still broken on Apple's end, so please send them feedback.
Mixing the headers of two different versions of anything can't be expected to work. It looks like HandBrake should use the ncurses port instead of the system ncurses.