使用 ocamlbuild 构建 SDL 和 OpenGL 应用程序
Using ocamlbuild to build SDL and OpenGL application
我正在尝试使用 ocamlsdl 和 lablgl 创建一个 OCaml 程序,但我不知道如何编译它。相关资料如下:
注意:ocamlfind 未找到 ocamlsdl。当我转到 .opam 的 lib 目录时,我找到了一个 ocamlsdl 文件夹,但它只有一个名为 opam.config 的空文件。我注意到的一件奇怪的事情是 main.byte 编译但不起作用,但是 main.native 根本不编译。
$opam list
# Installed packages for 4.01.0:
...
lablgl 1.05 Interface to OpenGL
ocamlsdl 0.9.1 Interface between OCaml and SDL
$ocamlfind list
lablgl (version: 1.05)
lablgl.glut (version: 1.01)
lablgl.togl (version: 1.01)
labltk (version: [distributed with Ocaml])
...
ocamlbuild (version: [distributed with Ocaml])
ocplib-endian (version: 0.8)
...
sdl (version: 0.9.1)
sdl.sdlgfx (version: n/a)
sdl.sdlimage (version: n/a)
sdl.sdlmixer (version: n/a)
sdl.sdlttf (version: n/a)
$ cat main.ml
let main () =
Sdl.init [`VIDEO];
Sdlvideo.set_video_mode 200 200 [];
Sdltimer.delay 2000;
Sdl.quit ()
let _ = main ()
$ cat _tags
<*.ml> or "main.native" or "main.byte": package(lablgl), package(sdl)
$ ocamlbuild -use-ocamlfind main.byte
Finished, 3 targets (3 cached) in 00:00:00.
$ ./main.byte
2015-05-14 10:02:01.208 ocamlrun[5426:707] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Error (1000) creating CGSWindow on line 259'
*** First throw call stack:
(
0 CoreFoundation 0x00007fff90d64b06 __exceptionPreprocess + 198
1 libobjc.A.dylib 0x00007fff8a3503f0 objc_exception_throw + 43
2 CoreFoundation 0x00007fff90d648dc +[NSException raise:format:] + 204
3 AppKit 0x00007fff8e84cb49 _NSCreateWindowWithOpaqueShape2 + 655
4 AppKit 0x00007fff8e84b340 -[NSWindow _commonAwake] + 2002
5 AppKit 0x00007fff8e809d82 -[NSWindow _commonInitFrame:styleMask:backing:defer:] + 1763
6 AppKit 0x00007fff8e808ecf -[NSWindow _initContent:styleMask:backing:defer:contentView:] + 1568
7 AppKit 0x00007fff8e80889f -[NSWindow initWithContentRect:styleMask:backing:defer:] + 45
8 libSDL-1.2.0.dylib 0x000000010a132077 -[SDL_QuartzWindow initWithContentRect:styleMask:backing:defer:] + 279
9 libSDL-1.2.0.dylib 0x000000010a12fb49 QZ_SetVideoMode + 2633
10 libSDL-1.2.0.dylib 0x000000010a125a89 SDL_SetVideoMode + 937
11 dllsdlstub.so 0x000000010a0f6d40 ml_SDL_SetVideoMode + 112
12 ocamlrun 0x0000000109cf1bcb caml_interprete + 40843
13 ocamlrun 0x0000000109cf9304 caml_main + 1124
14 ocamlrun 0x0000000109d1175c main + 12
15 libdyld.dylib 0x00007fff922437e1 start + 0
)
libc++abi.dylib: terminate called throwing an exception
Abort trap: 6
$ ocamlbuild -use-ocamlfind main.native
+ ocamlfind ocamlopt -linkpkg -package lablgl -package sdl main.cmx -o main.native
Undefined symbols for architecture x86_64:
"_CFBundleCopyBundleURL", referenced from:
-[SDLMain setupWorkingDirectory:] in libSDLmain.a(SDLMain.o)
"_CFBundleGetInfoDictionary", referenced from:
_main in libSDLmain.a(SDLMain.o)
"_CFBundleGetMainBundle", referenced from:
-[SDLMain setupWorkingDirectory:] in libSDLmain.a(SDLMain.o)
_main in libSDLmain.a(SDLMain.o)
"_CFRelease", referenced from:
-[SDLMain setupWorkingDirectory:] in libSDLmain.a(SDLMain.o)
"_CFURLCreateCopyDeletingLastPathComponent", referenced from:
-[SDLMain setupWorkingDirectory:] in libSDLmain.a(SDLMain.o)
"_CFURLGetFileSystemRepresentation", referenced from:
-[SDLMain setupWorkingDirectory:] in libSDLmain.a(SDLMain.o)
"_CPSEnableForegroundOperation", referenced from:
_main in libSDLmain.a(SDLMain.o)
"_CPSGetCurrentProcess", referenced from:
_main in libSDLmain.a(SDLMain.o)
"_CPSSetFrontProcess", referenced from:
_main in libSDLmain.a(SDLMain.o)
"_NSAllocateMemoryPages", referenced from:
-[NSString(ReplaceSubString) stringByReplacingRange:with:] in libSDLmain.a(SDLMain.o)
"_NSApp", referenced from:
_main in libSDLmain.a(SDLMain.o)
"_NSDeallocateMemoryPages", referenced from:
-[NSString(ReplaceSubString) stringByReplacingRange:with:] in libSDLmain.a(SDLMain.o)
"_OBJC_CLASS_$_NSApplication", referenced from:
l_OBJC_$_CATEGORY_NSApplication_$_SDLApplication in libSDLmain.a(SDLMain.o)
objc-class-ref in libSDLmain.a(SDLMain.o)
"_OBJC_CLASS_$_NSAutoreleasePool", referenced from:
objc-class-ref in libSDLmain.a(SDLMain.o)
"_OBJC_CLASS_$_NSMenu", referenced from:
objc-class-ref in libSDLmain.a(SDLMain.o)
"_OBJC_CLASS_$_NSMenuItem", referenced from:
objc-class-ref in libSDLmain.a(SDLMain.o)
"_OBJC_CLASS_$_NSObject", referenced from:
_OBJC_CLASS_$_SDLMain in libSDLmain.a(SDLMain.o)
"_OBJC_CLASS_$_NSProcessInfo", referenced from:
objc-class-ref in libSDLmain.a(SDLMain.o)
"_OBJC_CLASS_$_NSString", referenced from:
l_OBJC_$_CATEGORY_NSString_$_ReplaceSubString in libSDLmain.a(SDLMain.o)
objc-class-ref in libSDLmain.a(SDLMain.o)
"_OBJC_METACLASS_$_NSObject", referenced from:
_OBJC_METACLASS_$_SDLMain in libSDLmain.a(SDLMain.o)
"___CFConstantStringClassReference", referenced from:
CFString in libSDLmain.a(SDLMain.o)
CFString in libSDLmain.a(SDLMain.o)
CFString in libSDLmain.a(SDLMain.o)
CFString in libSDLmain.a(SDLMain.o)
CFString in libSDLmain.a(SDLMain.o)
CFString in libSDLmain.a(SDLMain.o)
CFString in libSDLmain.a(SDLMain.o)
...
"__objc_empty_cache", referenced from:
_OBJC_METACLASS_$_SDLMain in libSDLmain.a(SDLMain.o)
_OBJC_CLASS_$_SDLMain in libSDLmain.a(SDLMain.o)
"__objc_empty_vtable", referenced from:
_OBJC_METACLASS_$_SDLMain in libSDLmain.a(SDLMain.o)
_OBJC_CLASS_$_SDLMain in libSDLmain.a(SDLMain.o)
"_objc_msgSend", referenced from:
-[SDLMain application:openFile:] in libSDLmain.a(SDLMain.o)
-[SDLMain applicationDidFinishLaunching:] in libSDLmain.a(SDLMain.o)
-[NSString(ReplaceSubString) stringByReplacingRange:with:] in libSDLmain.a(SDLMain.o)
_main in libSDLmain.a(SDLMain.o)
"_objc_msgSend_fixup", referenced from:
l_objc_msgSend_fixup_length in libSDLmain.a(SDLMain.o)
l_objc_msgSend_fixup_alloc in libSDLmain.a(SDLMain.o)
l_objc_msgSend_fixup_release in libSDLmain.a(SDLMain.o)
l_objc_msgSend_fixup_objectForKey_ in libSDLmain.a(SDLMain.o)
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status
File "caml_startup", line 1:
Error: Error during linking
Command exited with code 2.
Compilation unsuccessful after building 4 targets (3 cached) in 00:00:00.
也许问题是我没有链接 SDL 框架,但我不知道如何使用 ocamlbuild 链接。关于如何编译这个有什么想法吗?
关于字节码堆栈跟踪,SDLMain 似乎没有被 link 编辑。您应该确保可执行文件在 -custom
模式下被 link 编辑,这可以通过以下方式实现添加一个:
<main.byte> : custom
到您的 _tags
文件。解释了其原因 here。
然后查看输出:
> ocamlobjinfo $(opam config var lib)/sdl/sdl.cmxa | grep Extra
Extra C object files: -lsdlstub -L/usr/local/lib -lSDLmain -lSDL
似乎 link 反对 OSX Cocoa 框架的需要没有记录在 cmxa
中(也许这应该报告上游)。所以你应该在你的目录中添加以下内容:
> cat myocamlbuild.ml
open Ocamlbuild_plugin
let () =
dispatch begin function
| After_rules ->
flag ["link"; "ocaml"; "link_cocoa"] (S [A "-cclib"; A "-framework Cocoa"])
| _ -> ()
end
您的 _tags
文件应如下所示:
> cat _tags
<*.{ml,byte,native}> : package(sdl), link_cocoa
<main.byte> : custom
使用这个我可以在我的机器上编译你的例子。
我正在尝试使用 ocamlsdl 和 lablgl 创建一个 OCaml 程序,但我不知道如何编译它。相关资料如下:
注意:ocamlfind 未找到 ocamlsdl。当我转到 .opam 的 lib 目录时,我找到了一个 ocamlsdl 文件夹,但它只有一个名为 opam.config 的空文件。我注意到的一件奇怪的事情是 main.byte 编译但不起作用,但是 main.native 根本不编译。
$opam list
# Installed packages for 4.01.0:
...
lablgl 1.05 Interface to OpenGL
ocamlsdl 0.9.1 Interface between OCaml and SDL
$ocamlfind list
lablgl (version: 1.05)
lablgl.glut (version: 1.01)
lablgl.togl (version: 1.01)
labltk (version: [distributed with Ocaml])
...
ocamlbuild (version: [distributed with Ocaml])
ocplib-endian (version: 0.8)
...
sdl (version: 0.9.1)
sdl.sdlgfx (version: n/a)
sdl.sdlimage (version: n/a)
sdl.sdlmixer (version: n/a)
sdl.sdlttf (version: n/a)
$ cat main.ml
let main () =
Sdl.init [`VIDEO];
Sdlvideo.set_video_mode 200 200 [];
Sdltimer.delay 2000;
Sdl.quit ()
let _ = main ()
$ cat _tags
<*.ml> or "main.native" or "main.byte": package(lablgl), package(sdl)
$ ocamlbuild -use-ocamlfind main.byte
Finished, 3 targets (3 cached) in 00:00:00.
$ ./main.byte
2015-05-14 10:02:01.208 ocamlrun[5426:707] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Error (1000) creating CGSWindow on line 259'
*** First throw call stack:
(
0 CoreFoundation 0x00007fff90d64b06 __exceptionPreprocess + 198
1 libobjc.A.dylib 0x00007fff8a3503f0 objc_exception_throw + 43
2 CoreFoundation 0x00007fff90d648dc +[NSException raise:format:] + 204
3 AppKit 0x00007fff8e84cb49 _NSCreateWindowWithOpaqueShape2 + 655
4 AppKit 0x00007fff8e84b340 -[NSWindow _commonAwake] + 2002
5 AppKit 0x00007fff8e809d82 -[NSWindow _commonInitFrame:styleMask:backing:defer:] + 1763
6 AppKit 0x00007fff8e808ecf -[NSWindow _initContent:styleMask:backing:defer:contentView:] + 1568
7 AppKit 0x00007fff8e80889f -[NSWindow initWithContentRect:styleMask:backing:defer:] + 45
8 libSDL-1.2.0.dylib 0x000000010a132077 -[SDL_QuartzWindow initWithContentRect:styleMask:backing:defer:] + 279
9 libSDL-1.2.0.dylib 0x000000010a12fb49 QZ_SetVideoMode + 2633
10 libSDL-1.2.0.dylib 0x000000010a125a89 SDL_SetVideoMode + 937
11 dllsdlstub.so 0x000000010a0f6d40 ml_SDL_SetVideoMode + 112
12 ocamlrun 0x0000000109cf1bcb caml_interprete + 40843
13 ocamlrun 0x0000000109cf9304 caml_main + 1124
14 ocamlrun 0x0000000109d1175c main + 12
15 libdyld.dylib 0x00007fff922437e1 start + 0
)
libc++abi.dylib: terminate called throwing an exception
Abort trap: 6
$ ocamlbuild -use-ocamlfind main.native
+ ocamlfind ocamlopt -linkpkg -package lablgl -package sdl main.cmx -o main.native
Undefined symbols for architecture x86_64:
"_CFBundleCopyBundleURL", referenced from:
-[SDLMain setupWorkingDirectory:] in libSDLmain.a(SDLMain.o)
"_CFBundleGetInfoDictionary", referenced from:
_main in libSDLmain.a(SDLMain.o)
"_CFBundleGetMainBundle", referenced from:
-[SDLMain setupWorkingDirectory:] in libSDLmain.a(SDLMain.o)
_main in libSDLmain.a(SDLMain.o)
"_CFRelease", referenced from:
-[SDLMain setupWorkingDirectory:] in libSDLmain.a(SDLMain.o)
"_CFURLCreateCopyDeletingLastPathComponent", referenced from:
-[SDLMain setupWorkingDirectory:] in libSDLmain.a(SDLMain.o)
"_CFURLGetFileSystemRepresentation", referenced from:
-[SDLMain setupWorkingDirectory:] in libSDLmain.a(SDLMain.o)
"_CPSEnableForegroundOperation", referenced from:
_main in libSDLmain.a(SDLMain.o)
"_CPSGetCurrentProcess", referenced from:
_main in libSDLmain.a(SDLMain.o)
"_CPSSetFrontProcess", referenced from:
_main in libSDLmain.a(SDLMain.o)
"_NSAllocateMemoryPages", referenced from:
-[NSString(ReplaceSubString) stringByReplacingRange:with:] in libSDLmain.a(SDLMain.o)
"_NSApp", referenced from:
_main in libSDLmain.a(SDLMain.o)
"_NSDeallocateMemoryPages", referenced from:
-[NSString(ReplaceSubString) stringByReplacingRange:with:] in libSDLmain.a(SDLMain.o)
"_OBJC_CLASS_$_NSApplication", referenced from:
l_OBJC_$_CATEGORY_NSApplication_$_SDLApplication in libSDLmain.a(SDLMain.o)
objc-class-ref in libSDLmain.a(SDLMain.o)
"_OBJC_CLASS_$_NSAutoreleasePool", referenced from:
objc-class-ref in libSDLmain.a(SDLMain.o)
"_OBJC_CLASS_$_NSMenu", referenced from:
objc-class-ref in libSDLmain.a(SDLMain.o)
"_OBJC_CLASS_$_NSMenuItem", referenced from:
objc-class-ref in libSDLmain.a(SDLMain.o)
"_OBJC_CLASS_$_NSObject", referenced from:
_OBJC_CLASS_$_SDLMain in libSDLmain.a(SDLMain.o)
"_OBJC_CLASS_$_NSProcessInfo", referenced from:
objc-class-ref in libSDLmain.a(SDLMain.o)
"_OBJC_CLASS_$_NSString", referenced from:
l_OBJC_$_CATEGORY_NSString_$_ReplaceSubString in libSDLmain.a(SDLMain.o)
objc-class-ref in libSDLmain.a(SDLMain.o)
"_OBJC_METACLASS_$_NSObject", referenced from:
_OBJC_METACLASS_$_SDLMain in libSDLmain.a(SDLMain.o)
"___CFConstantStringClassReference", referenced from:
CFString in libSDLmain.a(SDLMain.o)
CFString in libSDLmain.a(SDLMain.o)
CFString in libSDLmain.a(SDLMain.o)
CFString in libSDLmain.a(SDLMain.o)
CFString in libSDLmain.a(SDLMain.o)
CFString in libSDLmain.a(SDLMain.o)
CFString in libSDLmain.a(SDLMain.o)
...
"__objc_empty_cache", referenced from:
_OBJC_METACLASS_$_SDLMain in libSDLmain.a(SDLMain.o)
_OBJC_CLASS_$_SDLMain in libSDLmain.a(SDLMain.o)
"__objc_empty_vtable", referenced from:
_OBJC_METACLASS_$_SDLMain in libSDLmain.a(SDLMain.o)
_OBJC_CLASS_$_SDLMain in libSDLmain.a(SDLMain.o)
"_objc_msgSend", referenced from:
-[SDLMain application:openFile:] in libSDLmain.a(SDLMain.o)
-[SDLMain applicationDidFinishLaunching:] in libSDLmain.a(SDLMain.o)
-[NSString(ReplaceSubString) stringByReplacingRange:with:] in libSDLmain.a(SDLMain.o)
_main in libSDLmain.a(SDLMain.o)
"_objc_msgSend_fixup", referenced from:
l_objc_msgSend_fixup_length in libSDLmain.a(SDLMain.o)
l_objc_msgSend_fixup_alloc in libSDLmain.a(SDLMain.o)
l_objc_msgSend_fixup_release in libSDLmain.a(SDLMain.o)
l_objc_msgSend_fixup_objectForKey_ in libSDLmain.a(SDLMain.o)
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status
File "caml_startup", line 1:
Error: Error during linking
Command exited with code 2.
Compilation unsuccessful after building 4 targets (3 cached) in 00:00:00.
也许问题是我没有链接 SDL 框架,但我不知道如何使用 ocamlbuild 链接。关于如何编译这个有什么想法吗?
关于字节码堆栈跟踪,SDLMain 似乎没有被 link 编辑。您应该确保可执行文件在 -custom
模式下被 link 编辑,这可以通过以下方式实现添加一个:
<main.byte> : custom
到您的 _tags
文件。解释了其原因 here。
然后查看输出:
> ocamlobjinfo $(opam config var lib)/sdl/sdl.cmxa | grep Extra
Extra C object files: -lsdlstub -L/usr/local/lib -lSDLmain -lSDL
似乎 link 反对 OSX Cocoa 框架的需要没有记录在 cmxa
中(也许这应该报告上游)。所以你应该在你的目录中添加以下内容:
> cat myocamlbuild.ml
open Ocamlbuild_plugin
let () =
dispatch begin function
| After_rules ->
flag ["link"; "ocaml"; "link_cocoa"] (S [A "-cclib"; A "-framework Cocoa"])
| _ -> ()
end
您的 _tags
文件应如下所示:
> cat _tags
<*.{ml,byte,native}> : package(sdl), link_cocoa
<main.byte> : custom
使用这个我可以在我的机器上编译你的例子。