./index.html ../index.html

OpenGL featuring O'Caml ←英語デタラメ

Haskellが理論重視なら、ML系は実用重視。 その中でも広く使われているObjective Camlを使ってLet's関数型言語でOpenGL!

OCamlGL

必要なもの

ライブラリのビルド

O'Camlのインストール後再起動したら、ビルド開始。 gl, hgl, glfw, demos\simple\fountainの各ディレクトリでnmake makefile.winを実行します。 Microsoft製nmakeを持ってない人は、他社のmake.exeでごまかす。 (僕の場合はBorland製を使用)

glディレクトリ

...\ocamlgl\gl>make -f makefile.win
MAKE Version 5.2  Copyright (c) 1987, 1998 Inprise Corp.
        ocamlc -c -thread -g gl.ml
        ocamlopt -thread -c -unsafe -noassert gl.ml
        ocamlc -thread -c -ccopt "/Ox /G5" cgl.c -o cgl.obj
cl : Command line warning D4029 : optimization is not available in the standard
edition compiler
cgl.c
cgl.c(22028) : warning C4098: 'init_ov_FreeMemoryNV' : 'void' function returning
 a value
        link -lib /nologo /out:libgl.lib cgl.obj
        ocamlc -thread -g -a -o gl.cma -custom gl.cmo -cclib -lgl
        ocamlopt -thread -unsafe -noassert -a -o gl.cmxa gl.cmx -cclib -lgl
link /lib /nologo /debugtype:cv /out:"gl.lib" "gl.obj"
        link -lib /nologo /out:libgl.lib cgl.obj
        ocamlc -thread -g -a -o gl.cma -custom gl.cmo -cclib -lgl
        ocamlopt -thread -unsafe -noassert -a -o gl.cmxa gl.cmx -cclib -lgl
link /lib /nologo /debugtype:cv /out:"gl.lib" "gl.obj"
        link -lib /nologo /out:libgl.lib cgl.obj
        ocamlc -thread -g -a -o gl.cma -custom gl.cmo -cclib -lgl
        ocamlopt -thread -unsafe -noassert -a -o gl.cmxa gl.cmx -cclib -lgl
link /lib /nologo /debugtype:cv /out:"gl.lib" "gl.obj"
        link -lib /nologo /out:libgl.lib cgl.obj
        ocamlc -thread -g -a -o gl.cma -custom gl.cmo -cclib -lgl
        ocamlopt -thread -unsafe -noassert -a -o gl.cmxa gl.cmx -cclib -lgl
link /lib /nologo /debugtype:cv /out:"gl.lib" "gl.obj"
        copy gl.cma ..\lib
        1 個のファイルをコピーしました。
        copy gl.cmxa ..\lib
        1 個のファイルをコピーしました。
        copy gl.lib ..\lib
        1 個のファイルをコピーしました。
        copy gl.cmi ..\lib
        1 個のファイルをコピーしました。
        copy libgl.lib ..\lib
        1 個のファイルをコピーしました。
        copy gl.cma ..\lib
        1 個のファイルをコピーしました。
        copy gl.cmxa ..\lib
        1 個のファイルをコピーしました。
        copy gl.lib ..\lib
        1 個のファイルをコピーしました。
        copy gl.cmi ..\lib
        1 個のファイルをコピーしました。
        copy libgl.lib ..\lib
        1 個のファイルをコピーしました。
        copy gl.cma ..\lib
        1 個のファイルをコピーしました。
        copy gl.cmxa ..\lib
        1 個のファイルをコピーしました。
        copy gl.lib ..\lib
        1 個のファイルをコピーしました。
        copy gl.cmi ..\lib
        1 個のファイルをコピーしました。
        copy libgl.lib ..\lib
        1 個のファイルをコピーしました。
        copy gl.cma ..\lib
        1 個のファイルをコピーしました。
        copy gl.cmxa ..\lib
        1 個のファイルをコピーしました。
        copy gl.lib ..\lib
        1 個のファイルをコピーしました。
        copy gl.cmi ..\lib
        1 個のファイルをコピーしました。
        copy libgl.lib ..\lib
        1 個のファイルをコピーしました。
        copy gl.cma ..\lib
        1 個のファイルをコピーしました。
        copy gl.cmxa ..\lib
        1 個のファイルをコピーしました。
        copy gl.lib ..\lib
        1 個のファイルをコピーしました。
        copy gl.cmi ..\lib
        1 個のファイルをコピーしました。
        copy libgl.lib ..\lib
        1 個のファイルをコピーしました。

...\ocamlgl\gl>

hglディレクトリ

...\ocamlgl\hgl>make -f makefile.win
MAKE Version 5.2  Copyright (c) 1987, 1998 Inprise Corp.
        ocamlc -c -thread -g -I ..\lib hgl.ml
        ocamlopt -thread -c -unsafe -noassert -I ..\lib hgl.ml
        ocamlc -thread -c -ccopt "/Ox /G5" chgl.c -o chgl.obj
cl : Command line warning D4029 : optimization is not available in the standard
edition compiler
chgl.c
        lib /nologo /out:libhgl.lib chgl.obj
link /lib /nologo /out:libhgl.lib chgl.obj
        ocamlc -thread -g -a -o hgl.cma -custom hgl.cmo -cclib -lhgl
        ocamlopt -thread -unsafe -noassert -a -o hgl.cmxa hgl.cmx -cclib -lhgl
link /lib /nologo /debugtype:cv /out:"hgl.lib" "hgl.obj"
        lib /nologo /out:libhgl.lib chgl.obj
link /lib /nologo /out:libhgl.lib chgl.obj
        ocamlc -thread -g -a -o hgl.cma -custom hgl.cmo -cclib -lhgl
        ocamlopt -thread -unsafe -noassert -a -o hgl.cmxa hgl.cmx -cclib -lhgl
link /lib /nologo /debugtype:cv /out:"hgl.lib" "hgl.obj"
        lib /nologo /out:libhgl.lib chgl.obj
link /lib /nologo /out:libhgl.lib chgl.obj
        ocamlc -thread -g -a -o hgl.cma -custom hgl.cmo -cclib -lhgl
        ocamlopt -thread -unsafe -noassert -a -o hgl.cmxa hgl.cmx -cclib -lhgl
link /lib /nologo /debugtype:cv /out:"hgl.lib" "hgl.obj"
        lib /nologo /out:libhgl.lib chgl.obj
link /lib /nologo /out:libhgl.lib chgl.obj
        ocamlc -thread -g -a -o hgl.cma -custom hgl.cmo -cclib -lhgl
        ocamlopt -thread -unsafe -noassert -a -o hgl.cmxa hgl.cmx -cclib -lhgl
link /lib /nologo /debugtype:cv /out:"hgl.lib" "hgl.obj"
        for %i in (hgl.cma hgl.cmxa libhgl.lib hgl.lib hgl.cmi) do copy %i ..\li
b

...\ocamlgl\hgl>copy hgl.cma ..\lib
        1 個のファイルをコピーしました。

...\ocamlgl\hgl>copy hgl.cmxa ..\lib
        1 個のファイルをコピーしました。

...\ocamlgl\hgl>copy libhgl.lib ..\lib
        1 個のファイルをコピーしました。

...\ocamlgl\hgl>copy hgl.lib ..\lib
        1 個のファイルをコピーしました。

...\ocamlgl\hgl>copy hgl.cmi ..\lib
        1 個のファイルをコピーしました。

...\ocamlgl\hgl>

glfwディレクトリ

こいつが難関です。 VisualC++を持っていないのにごまかしているせいかもしれませんけどね。 cannot open input file 'opengl32.lib'なんて言われたら、その都度*.libをカレントディレクトリにコピーしたり。 環境変数libを見てないのかと言いたくなるぐらい。 最終的にはAdvAPI32.Lib Kernel32.Lib libcmt.lib oldnames.lib OpenGL32.Lib User32.Lib Uuid.Libが必要です。 僕の環境の場合。

cglfw.cが、OpenGL32.libによっては存在しない関数を呼んでいたり。

CAMLprim void ml_glfwSetGLlib(value name)
{
    CAMLparam1(name);
    /* _glfwSetGLlib(String_val(name)); */
    CAMLreturn0;
}

makefileに参照するライブラリを書き足してやったり。

glfw.cmi glfw.cmo glfw.cmx: glfw.ml
  ocamlc -thread -c glfw.ml
  ocamlopt -thread -unsafe -noassert glfw.ml (実際には改行しません)
    opengl32.lib user32.lib cglfw.obj -cclib -lglfw
...\ocamlgl\glfw>make -f makefile.win
MAKE Version 5.2  Copyright (c) 1987, 1998 Inprise Corp.
        cl /c /Ox /MT /G5 win32/input.c /Foinput.obj
Microsoft (R) 32-bit C/C++ Standard Compiler Version 13.10.3077 for 80x86
Copyright (C) Microsoft Corporation 1984-2002. All rights reserved.

cl : Command line warning D4029 : optimization is not available in the standard
edition compiler
input.c
        cl /c /Ox /MT /G5 win32/window.c /Fowindow.obj
Microsoft (R) 32-bit C/C++ Standard Compiler Version 13.10.3077 for 80x86
Copyright (C) Microsoft Corporation 1984-2002. All rights reserved.

cl : Command line warning D4029 : optimization is not available in the standard
edition compiler
window.c
        cl /c /Ox /MT /G5 win32/init.c /Foinit.obj
Microsoft (R) 32-bit C/C++ Standard Compiler Version 13.10.3077 for 80x86
Copyright (C) Microsoft Corporation 1984-2002. All rights reserved.

cl : Command line warning D4029 : optimization is not available in the standard
edition compiler
init.c
        cl /c /Ox /MT /G5 win32/joystick.c /Fojoystick.obj
Microsoft (R) 32-bit C/C++ Standard Compiler Version 13.10.3077 for 80x86
Copyright (C) Microsoft Corporation 1984-2002. All rights reserved.

cl : Command line warning D4029 : optimization is not available in the standard
edition compiler
joystick.c
        cl /c /Ox /MT /G5 win32/glext.c /Foglext.obj
Microsoft (R) 32-bit C/C++ Standard Compiler Version 13.10.3077 for 80x86
Copyright (C) Microsoft Corporation 1984-2002. All rights reserved.

cl : Command line warning D4029 : optimization is not available in the standard
edition compiler
glext.c
        cl /c /Ox /MT /G5 win32/fullscreen.c /Fofullscreen.obj
Microsoft (R) 32-bit C/C++ Standard Compiler Version 13.10.3077 for 80x86
Copyright (C) Microsoft Corporation 1984-2002. All rights reserved.

cl : Command line warning D4029 : optimization is not available in the standard
edition compiler
fullscreen.c
        cl /c /Ox /MT /G5 win32/enable.c /Foenable.obj
Microsoft (R) 32-bit C/C++ Standard Compiler Version 13.10.3077 for 80x86
Copyright (C) Microsoft Corporation 1984-2002. All rights reserved.

cl : Command line warning D4029 : optimization is not available in the standard
edition compiler
enable.c
        ocamlc -thread -c cglfw.c -o cglfw.obj
cl : Command line warning D4029 : optimization is not available in the standard
edition compiler
cglfw.c
        lib /nologo /out:libglfw.lib input.obj window.obj init.obj joystick.obj
glext.obj fullscreen.obj enable.obj cglfw.obj
link /lib /nologo /out:libglfw.lib input.obj window.obj init.obj joystick.obj gl
ext.obj fullscreen.obj enable.obj cglfw.obj
        ocamlc -thread -c glfw.ml
        ocamlopt -thread -unsafe -noassert glfw.ml opengl32.lib user32.lib cglfw
.obj -cclib -lglfw
        ocamlc -a -thread -o glfw.cma -custom glfw.cmo -cclib -lglfw
        ocamlopt -a -thread -o glfw.cmxa glfw.cmx -cclib -lglfw
link /lib /nologo /debugtype:cv /out:"glfw.lib" "glfw.obj"
        ocamlc -a -thread -o glfw.cma -custom glfw.cmo -cclib -lglfw
        ocamlopt -a -thread -o glfw.cmxa glfw.cmx -cclib -lglfw
link /lib /nologo /debugtype:cv /out:"glfw.lib" "glfw.obj"
        ocamlc -a -thread -o glfw.cma -custom glfw.cmo -cclib -lglfw
        ocamlopt -a -thread -o glfw.cmxa glfw.cmx -cclib -lglfw
link /lib /nologo /debugtype:cv /out:"glfw.lib" "glfw.obj"
        for %i in (libglfw.lib glfw.cma glfw.cmxa glfw.lib glfw.cmi) do copy %i
..\lib

...\ocamlgl\glfw>copy libglfw.lib ..\lib
        1 個のファイルをコピーしました。

...\ocamlgl\glfw>copy glfw.cma ..\lib
        1 個のファイルをコピーしました。

...\ocamlgl\glfw>copy glfw.cmxa ..\lib
        1 個のファイルをコピーしました。

...\ocamlgl\glfw>copy glfw.lib ..\lib
        1 個のファイルをコピーしました。

...\ocamlgl\glfw>copy glfw.cmi ..\lib
        1 個のファイルをコピーしました。

...\ocamlgl\glfw>

demos\simple\fountainディレクトリ

これはサンプルですね。

...\ocamlgl\demos\simple\fountain>make -f makefile.win
MAKE Version 5.2  Copyright (c) 1987, 1998 Inprise Corp.
        ocamlc -thread -I ..\..\..\lib glfw.cma bigarray.cma unix.cma gl.cma hgl
.cma fountain.ml -o fountain.byte.exe -ccopt user32.lib -ccopt opengl32.lib
camlprim308cd0.c
        ocamlopt -thread -unsafe -noassert -I ..\..\..\lib glfw.cmxa bigarray.cm
xa unix.cmxa gl.cmxa hgl.cmxa fountain.ml -o fountain.opt.exe -ccopt user32.lib
-ccopt opengl32.lib

...\ocamlgl\demos\simple\fountain>

動作画面は、冒頭の画像となります。

SDL?

一緒にSDL関係のラッパーが入っているような気がするのですが、makefileがついてませんです。 将来使えるようになるということでしょうか。

LablGL

必要なもの


*1 最適化はできませんけれどね。

*2 COFF用のlib.exeが手に入らない場合、実体はlink /libなので、次のようなラッパーを書けばOK。

{$APPTYPE CONSOLE}
uses Windows;
var s: string;
begin
  if CmdLine[0] = '"' then repeat Inc(CmdLine) until CmdLine^ = '"'
  else repeat Inc(CmdLine) until CmdLine^ = ' ';
  Inc(CmdLine);
  S := 'link /lib ' + cmdline;
  WinExec(PChar(S), SW_SHOW);
end.

*3 というよりWindowsにすらSHを要求するようなのがどうかしてるとしか思えないのですが。 それってLinuxでKylixが入ってるの前提にするようなものじゃないかと。 (…今回の話とは関係ないのですが、愚痴りたくなったもので…こうやってわざわざ欄外で愚痴ってますので許してください)