macOS 上的 Clang 无法从 ncurses 链接 lmenu
Clang on macOS fails linking lmenu from ncurses
我是 ncurses 库的新手,所以我一直在尝试重新创建此页面上的一些示例,http://www.tldp.org/HOWTO/NCURSES-Programming-HOWTO/index.html。
我已经了解了关于创建菜单的部分,特别是示例 21。我编写的程序适用于 Linux,特别是 Ubuntu 18.04,但我无法编译我正在使用菜单库。我使用 JUST ncurses 编写的所有其他示例程序都可以正常编译,没有问题,只是在我尝试使用菜单库时。
我用来在 Linux 和 macOS 上构建的命令是,
gcc libmenutest.c -o test -lmenu -lncurses
我尝试在 macOS 上移动 -lmenu -lncurses
并更改顺序,但没有成功。我已经通过 brew 安装了 ncurses,并尝试使用 brew 的 gcc-8,但也没有成功。
我 运行 几乎全新安装了 macOS 和最新的命令行工具。我可以在 /usr/lib
中看到 libmenu,与 libncurses 相同。所以我真的很困惑为什么编译器找不到它。
这是我用来诊断问题的一些测试代码。
#include <curses.h>
#include <menu.h>
#include <stdlib.h>
#define ARRAY_SIZE(a) (sizeof a / sizeof a[0])
int main (void)
{
int i;
int nchoices;
char *choices[] = {
"Choice 1", "Choice 2", "Choice 3", "Exit", (char *) NULL,
};
// Test that the types are present, this should test for the include headers
ITEM **items;
MENU *menu;
WINDOW *win;
// This will test for includes and to see if libncurses can be linked
initscr ();
noecho ();
cbreak ();
keypad (stdscr, TRUE);
// this bit will test for libmenu include and if it can be linked
nchoices = ARRAY_SIZE (choices);
items = calloc (nchoices, sizeof (ITEM *));
if (items == NULL) exit (1);
for (i = 0; i < nchoices; i++)
items[i] = new_item (choices[i], choices[i]);
// write smarmy message to screen :^^^^^^)
printw ("This worked :^)");
refresh ();
getch ();
// clean up
for (i = 0; i < nchoices; i++)
free_item (items[i]);
endwin ();
return 0;
}
这是我现在得到的输出...
Undefined symbols for architecture x86_64:
"_free_item", referenced from:
_main in libmenutest-0f0c39.o
"_new_item", referenced from:
_main in libmenutest-0f0c39.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
您可以执行以下操作:
brew install ncurses
由于 macOS 已经包含一个 ncurses 版本,brew 在 /usr/local/opt/ncurses
中安装了它的替代版本。
为了让编译器和链接器可以访问它,您的构建命令现在应该如下所示:
gcc -I/usr/local/opt/ncurses/include -L/usr/local/opt/ncurses/lib libmenutest.c -o test -lmenu -lncurses
当你最终调用你的程序时,输出如下:
This worked :^)
CMake
对于使用 CMake 的人,您的 CMakeLists.txt 可能如下所示:
cmake_minimum_required(VERSION 3.14)
project(libmenutest C)
set(CMAKE_C_STANDARD 99)
include_directories(/usr/local/opt/ncurses/include)
link_directories(/usr/local/opt/ncurses/lib)
add_executable(libmenutest libmenutest.c)
target_link_libraries(libmenutest menu ncurses)
同样的问题。我终于用下面的命令解决了它:
- 编译成位码
clang -c -o libmenutest.o libmenutest.c
- link 没有 -syslibroot,clang 自动生成
ld -demangle -lto_library /Library/Developer/CommandLineTools/usr/lib/libLTO.dylib -no_deduplicate -dynamic -arch x86_64 -platform_version macos 10.15.0 10.15.6 -lSystem /Library/Developer/CommandLineTools/usr/lib/clang/12.0.0/lib/darwin/libclang_rt.osx.a -o a.out libmenutest.o -lmenu -lncurses
为什么上面的代码有效? ncurses 库的默认搜索路径是:
-lmenu
=> /usr/lib/libmenu.dylib
-lncurses
=> /usr/lib/ncurses.dylib
与 -syslibroot /Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk
,他们变成:
-lmenu
=> /Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/usr/lib/libmenu.dylib
-lncurses
=> /Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/usr/lib/ncurses.dylib
这里是 ld
man 文档:
ld maintains a list of directories to search for a library or framework
to use. The default library search path is /usr/lib then /usr/local/lib.
The -L option will add a new library search path. The default framework
search path is /Library/Frameworks then /System/Library/Frameworks.
(Note: previously, /Network/Library/Frameworks was at the end of the
default path. If you need that functionality, you need to explicitly add
-F/Network/Library/Frameworks). The -F option will add a new framework
search path. The -Z option will remove the standard search paths. The
-syslibroot option will prepend a prefix to all search paths.
我是 ncurses 库的新手,所以我一直在尝试重新创建此页面上的一些示例,http://www.tldp.org/HOWTO/NCURSES-Programming-HOWTO/index.html。
我已经了解了关于创建菜单的部分,特别是示例 21。我编写的程序适用于 Linux,特别是 Ubuntu 18.04,但我无法编译我正在使用菜单库。我使用 JUST ncurses 编写的所有其他示例程序都可以正常编译,没有问题,只是在我尝试使用菜单库时。
我用来在 Linux 和 macOS 上构建的命令是,
gcc libmenutest.c -o test -lmenu -lncurses
我尝试在 macOS 上移动 -lmenu -lncurses
并更改顺序,但没有成功。我已经通过 brew 安装了 ncurses,并尝试使用 brew 的 gcc-8,但也没有成功。
我 运行 几乎全新安装了 macOS 和最新的命令行工具。我可以在 /usr/lib
中看到 libmenu,与 libncurses 相同。所以我真的很困惑为什么编译器找不到它。
这是我用来诊断问题的一些测试代码。
#include <curses.h>
#include <menu.h>
#include <stdlib.h>
#define ARRAY_SIZE(a) (sizeof a / sizeof a[0])
int main (void)
{
int i;
int nchoices;
char *choices[] = {
"Choice 1", "Choice 2", "Choice 3", "Exit", (char *) NULL,
};
// Test that the types are present, this should test for the include headers
ITEM **items;
MENU *menu;
WINDOW *win;
// This will test for includes and to see if libncurses can be linked
initscr ();
noecho ();
cbreak ();
keypad (stdscr, TRUE);
// this bit will test for libmenu include and if it can be linked
nchoices = ARRAY_SIZE (choices);
items = calloc (nchoices, sizeof (ITEM *));
if (items == NULL) exit (1);
for (i = 0; i < nchoices; i++)
items[i] = new_item (choices[i], choices[i]);
// write smarmy message to screen :^^^^^^)
printw ("This worked :^)");
refresh ();
getch ();
// clean up
for (i = 0; i < nchoices; i++)
free_item (items[i]);
endwin ();
return 0;
}
这是我现在得到的输出...
Undefined symbols for architecture x86_64:
"_free_item", referenced from:
_main in libmenutest-0f0c39.o
"_new_item", referenced from:
_main in libmenutest-0f0c39.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
您可以执行以下操作:
brew install ncurses
由于 macOS 已经包含一个 ncurses 版本,brew 在 /usr/local/opt/ncurses
中安装了它的替代版本。
为了让编译器和链接器可以访问它,您的构建命令现在应该如下所示:
gcc -I/usr/local/opt/ncurses/include -L/usr/local/opt/ncurses/lib libmenutest.c -o test -lmenu -lncurses
当你最终调用你的程序时,输出如下:
This worked :^)
CMake
对于使用 CMake 的人,您的 CMakeLists.txt 可能如下所示:
cmake_minimum_required(VERSION 3.14)
project(libmenutest C)
set(CMAKE_C_STANDARD 99)
include_directories(/usr/local/opt/ncurses/include)
link_directories(/usr/local/opt/ncurses/lib)
add_executable(libmenutest libmenutest.c)
target_link_libraries(libmenutest menu ncurses)
同样的问题。我终于用下面的命令解决了它:
- 编译成位码
clang -c -o libmenutest.o libmenutest.c
- link 没有 -syslibroot,clang 自动生成
ld -demangle -lto_library /Library/Developer/CommandLineTools/usr/lib/libLTO.dylib -no_deduplicate -dynamic -arch x86_64 -platform_version macos 10.15.0 10.15.6 -lSystem /Library/Developer/CommandLineTools/usr/lib/clang/12.0.0/lib/darwin/libclang_rt.osx.a -o a.out libmenutest.o -lmenu -lncurses
为什么上面的代码有效? ncurses 库的默认搜索路径是:
-lmenu
=> /usr/lib/libmenu.dylib
-lncurses
=> /usr/lib/ncurses.dylib
与 -syslibroot /Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk
,他们变成:
-lmenu
=> /Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/usr/lib/libmenu.dylib
-lncurses
=> /Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/usr/lib/ncurses.dylib
这里是 ld
man 文档:
ld maintains a list of directories to search for a library or framework to use. The default library search path is /usr/lib then /usr/local/lib. The -L option will add a new library search path. The default framework search path is /Library/Frameworks then /System/Library/Frameworks. (Note: previously, /Network/Library/Frameworks was at the end of the default path. If you need that functionality, you need to explicitly add -F/Network/Library/Frameworks). The -F option will add a new framework search path. The -Z option will remove the standard search paths. The -syslibroot option will prepend a prefix to all search paths.