# Part of the A-A-P recipe executive
# Copyright (c) 2002-2004 Lars Ivar Igesund and stichting NLnet Labs
# Permission to copy and use this file is specified in the file COPYING.
# If this file is missing you can find it here: http://www.a-a-p.org/COPYING
#
# This module sets up variables and actions for using the DMD compiler tools.
#
from RecPython import *
import Global
from Action import action_add
from Dictlist import str2dictlist
from RecPos import RecPos
def exists():
"""
Return TRUE when the DMD toolchain can be found.
"""
if program_path("dmd"):
if os.name == "nt":
if program_path("link"):
return program_path("lib")
else:
return 0
else:
return program_path("gcc")
else:
return 0
def define_actions():
"""
Define the actions that DMD can accomplish.
"""
rd = Global.globals
# Compile one sourcefile at the time
define_action("compile_dmd", 0, """
opt =
@if _no.OPTIMIZE and int(_no.OPTIMIZE) > 0:
opt = -O
dbg =
DEBUG ?=
@if _no.DEBUG == 'yes':
dbg = -g
:sys $DMD $?DFLAGS $?DVERSION $opt $dbg $?DDEBUG $?DIMPORT -of$target
-c $source
""",
outtypes = ["object", "libobject", "dllobject"],
intypes = ["d"])
define_action("compile_dmd", 0, """
DLINKFLAGS += source
""",
intypes = ["def"])
# Build a program from object files
define_action("build_dmd", 0, """
DLINKFLAGS += /DELEXECUTABLE
dbg =
DEBUG ?=
@if _no.DEBUG == 'yes':
dbg = -g
opt =
@if _no.OPTIMIZE and int(_no.OPTIMIZE) > 0:
opt = -O
:sys $DMD $?DFLAGS $?DVERSION $opt $dbg $?DDEBUG $?DIMPORT
-L$*?DLINKFLAGS -L+$*?LIBS -of$target $source
""",
outtypes = ["default"],
intypes = ["object"])
# Build a static lib from object files
define_action("buildlib_dmd", 0, """
@if os.name == "nt":
:progsearch LIB lib
:sys $LIB $?DLINKFLAGS -p512 -c $target $source
@else:
:sys $AR -r $target $source
""",
outtypes = ["default"],
intypes = ["libobject"])
# Build a dll from object files
define_action("builddll_dmd", 0, """
DLINKFLAGS += /DELEXECUTABLE
@if os.name == "nt":
DIMPLIB ?=
@exec "import tools.dmd"
@if _no.DIMPLIB and _no.DIMPLIB == "yes":
DLINKFLAGS += /implib
@if not tools.dmd.find_dll_main_object(source):
@f = file("aap_dllmain.d", 'w')
@f.write(tools.dmd.dll_main_source())
@f.close()
:do compile {target = aap_dllmain.obj} aap_dllmain.d
source += aap_dllmain.obj
@if not tools.dmd.find_def_file(source):
@f = file("aap_dll.def", 'w')
@f.write(tools.dmd.dll_def_file(target))
@f.close()
source += aap_dll.def
:sys $DMD -L$*?DLINKFLAGS -L+$*?LIBS -of$target $source
@if os.name == "nt":
:del {f} {q} aap_dllmain.*
:del {f} {q} aap_dll.def
""",
outtypes = ["default"],
intypes = ["dllobject", "def"])
# Build a program directly from source
define_action("buildonestep_dmd", 0, """
DLINKFLAGS += /DELEXECUTABLE
opt =
@if _no.OPTIMIZE and int(_no.OPTIMIZE) > 0:
opt = -O
dbg =
DEBUG ?=
@if _no.DEBUG == 'yes':
dbg = -g
:sys $DMD $?DFLAGS $?DVERSION $opt $dbg $?DDEBUG $?DIMPORT
-L$*?DLINKFLAGS -L+$*?LIBS -of$target $source
:del {f} {q} *.obj
""",
outtypes = ["default"],
intypes = ["d"])
# Build a static lib directly from source
define_action("buildlibonestep_dmd", 0, """
opt =
@if _no.OPTIMIZE and int(_no.OPTIMIZE) > 0:
opt = -O
dbg =
DEBUG ?=
@if _no.DEBUG == 'yes':
dbg = -g
:sys $DMD -c $?DFLAGS $?DVERSION $opt $dbg $?DDEBUG $?DIMPORT
-op $source
BDIR =
objects = `src2obj(source)`
@if os.name == "nt":
:progsearch LIB lib
:sys $LIB $?DLINKFLAGS -p512 -c $target $objects
@else:
:sys $AR -r $target $source
:del {f} {q} *.$OBJSUF
""",
outtypes = ["default"],
intypes = ["d"])
# Build a dll directly from source
define_action("builddllonestep_dmd", 0, """
DLINKFLAGS += /DELEXECUTABLE
opt =
@if _no.OPTIMIZE and int(_no.OPTIMIZE) > 0:
opt = -O
dbg =
DEBUG ?=
@if _no.DEBUG == 'yes':
dbg = -g
@if os.name == "nt":
DIMPLIB ?=
@if DIMPLIB and DIMPLIB == "yes":
DLINKFLAGS += -L/implib
@exec "import tools.dmd"
@if not tools.dmd.find_dll_main_source(source):
@f = file("aap_dllmain.d", 'w')
@f.write(tools.dmd.dll_main_source())
@f.close()
source += aap_dllmain.d
@if not tools.dmd.find_def_file(source):
@f = file("aap_dll.def", 'w')
@f.write(tools.dmd.dll_def_file(target))
@f.close()
source += aap_dll.def
:sys $DMD $?DFLAGS $?DVERSION $opt $dbg $?DDEBUG $?DIMPORT
-L$*?DLINKFLAGS -L+$*?LIBS -of$target $source
@if os.name == "nt":
:del {f} {q} aap_dllmain.d
:del {f} {q} aap_dll.def
:del {q} *.obj
""",
outtypes = ["default"],
intypes = ["d", "def"])
if not rd["_top"].get("DMD"):
rd["_top"]["DMD"] = "dmd"
def use_actions(scope):
"""
Setup variables so that the default actions use the DMD actions.
"""
scope["D_COMPILE_ACTION"] = "compile_dmd"
scope["D_BUILD_ACTION"] = "build_dmd"
scope["D_BUILDLIB_ACTION"] = "buildlib_dmd"
scope["D_BUILDDLL_ACTION"] = "builddll_dmd"
scope["D_BUILDONESTEP_ACTION"] = "buildonestep_dmd"
scope["D_BUILDDLLONESTEP_ACTION"] = "builddllonestep_dmd"
scope["D_BUILDLIBONESTEP_ACTION"] = "buildlibonestep_dmd"
def find_phobos():
dmd_path = program_path("dmd")
import re
phobos_path = re.sub('bin', 'lib', dmd_path)
return re.sub('dmd.EXE', '', phobos_path)
def find_dll_main_source(sourcestr):
import re
m = re.compile(r"BOOL\s+DllMain\s*\(\s*HINSTANCE")
for si in var2list(sourcestr):
f = file2string(si)
if m.search(f):
return 1
return None
def find_dll_main_object(sourcestr):
for si in var2list(sourcestr):
f = file2string(si)
from string import find
if find(f, "_DllMain@12") > -1:
return 1
return None
def find_def_file(sourcestr):
print sourcestr
for si in var2list(sourcestr):
from string import find
if (find(si, ".def") > -1):
return 1
return None
def dll_main_source():
source = """
import std.c.windows.windows;
HINSTANCE g_hInst;
extern (C)
{
void gc_init();
void gc_term();
void _minit();
void _moduleCtor();
}
export:
extern (Windows)
BOOL DllMain(HINSTANCE hInstance,
ULONG ulReason,
LPVOID pvReserved)
{
switch (ulReason)
{
case DLL_PROCESS_ATTACH:
gc_init();
_minit();
_moduleCtor();
break;
case DLL_PROCESS_DETACH:
gc_term();
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
return false;
}
g_hInst = hInstance;
return true;
}
"""
return source
def dll_def_file(target):
from string import find
idx = find(target, ".dll")
source = "LIBRARY \"" + target[0:idx+4] + "\""
source = source + """
EXETYPE NT
SUBSYSTEM WINDOWS
CODE SHARED EXECUTE
DATA WRITE
"""
return source
# vim: set sw=4 et sts=4 tw=79 fo+=l:
|