# 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: