diff --git a/Makefile b/Makefile index 08239e9..c6a10b0 100644 --- a/Makefile +++ b/Makefile @@ -25,6 +25,8 @@ version.ml: Makefile echo "let version = \"$(VERSION)\"" > version.ml echo "let mingw_prefix = \"$(MINGW_PREFIX)\"" >> version.ml echo "let mingw64_prefix = \"$(MINGW64_PREFIX)\"" >> version.ml + echo "let cygwin_prefix = \"$(CYGWIN_PREFIX)\"" >> version.ml + echo "let cygwin64_prefix = \"$(CYGWIN64_PREFIX)\"" >> version.ml # Supported tool-chains @@ -51,6 +53,8 @@ MSVC_PREFIX= MSVC64_PREFIX= MSVCC=cl.exe $(MSVC_FLAGS) MSVCC64=cl.exe $(MSVC_FLAGS) +MSVC_CCPREFIX= +MSVC64_CCPREFIX= else ifeq ($(SDK),) # Otherwise, assume the 32-bit version of VS 2008 or Win7 SDK is in the path. @@ -67,6 +71,8 @@ MSVC64_PREFIX=LIB="$(MSVC64_LIB)" INCLUDE="$(MSVC_INCLUDE)" MSVCC = $(MSVCC_ROOT)/cl.exe $(MSVC_FLAGS) MSVCC64 = $(MSVCC_ROOT)/amd64/cl.exe $(MSVC_FLAGS) +MSVC_CCPREFIX=-cc-prefix $(MSVCC_ROOT)/ +MSVC64_CCPREFIX=-cc-prefix $(MSVCC_ROOT)/amd64/ else MSVCC_ROOT:= MSVC_PREFIX=PATH="$(SDK):$(PATH)" LIB="$(SDK_LIB);$(LIB)" INCLUDE="$(SDK_INC);$(INCLUDE)" @@ -74,6 +80,8 @@ MSVC64_PREFIX=PATH="$(SDK64):$(PATH)" LIB="$(SDK64_LIB);$(LIB)" INCLUDE="$(SDK64 MSVCC = cl.exe $(MSVC_FLAGS) MSVCC64 = cl.exe $(MSVC_FLAGS) +MSVC_CCPREFIX= +MSVC64_CCPREFIX= endif endif @@ -145,47 +153,26 @@ version.res: version.rc version_res.o: version.rc $(TOOLPREF)windres version.rc version_res.o -flexdll_msvc.obj: flexdll.h flexdll.c - $(MSVC_PREFIX) $(MSVCC) /DMSVC -c /Fo"flexdll_msvc.obj" flexdll.c +flexdll_initer_msvc.obj flexdll_msvc.obj: flexdll.h flexdll.c flexdll_initer.c flexlink.exe + $(MSVC_PREFIX) ./flexlink -v -install -o . -chain msvc $(MSVC_CCPREFIX) -flexdll_msvc64.obj: flexdll.h flexdll.c - $(MSVC64_PREFIX) $(MSVCC64) /DMSVC /DMSVC64 -c /Fo"flexdll_msvc64.obj" flexdll.c +flexdll_initer_msvc64.obj flexdll_msvc64.obj: flexdll.h flexdll.c flexdll_initer.c flexlink.exe + $(MSVC64_PREFIX) ./flexlink -v -install -o . -chain msvc64 $(MSVC64_CCPREFIX) -flexdll_cygwin.o: flexdll.h flexdll.c - $(CYGCC) -c -DCYGWIN -o flexdll_cygwin.o flexdll.c +flexdll_initer_cygwin.o flexdll_cygwin.o: flexdll.h flexdll.c flexdll_initer.c flexlink.exe + ./flexlink -v -install -o . -chain cygwin -flexdll_cygwin64.o: flexdll.h flexdll.c - $(CYG64CC) -c -DCYGWIN -o flexdll_cygwin64.o flexdll.c +flexdll_initer_cygwin64.o flexdll_cygwin64.o: flexdll.h flexdll.c flexdll_initer.c flexlink.exe + ./flexlink -v -install -o . -chain cygwin64 -flexdll_mingw.o: flexdll.h flexdll.c - $(MINCC) -c -DMINGW -o flexdll_mingw.o flexdll.c +flexdll_initer_mingw.o flexdll_mingw.o: flexdll.h flexdll.c flexdll_initer.c flexlink.exe + ./flexlink -v -install -o . -chain mingw -flexdll_gnat.o: flexdll.h flexdll.c - gcc -c -o flexdll_gnat.o flexdll.c +flexdll_initer_mingw64.o flexdll_mingw64.o: flexdll.h flexdll.c flexdll_initer.c flexlink.exe + ./flexlink -v -install -o . -chain mingw64 -flexdll_mingw64.o: flexdll.h flexdll.c - $(MIN64CC) -c -DMINGW -o flexdll_mingw64.o flexdll.c - -flexdll_initer_msvc.obj: flexdll_initer.c - $(MSVC_PREFIX) $(MSVCC) -c /Fo"flexdll_initer_msvc.obj" flexdll_initer.c - -flexdll_initer_msvc64.obj: flexdll_initer.c - $(MSVC64_PREFIX) $(MSVCC64) -c /Fo"flexdll_initer_msvc64.obj" flexdll_initer.c - -flexdll_initer_cygwin.o: flexdll_initer.c - $(CYGCC) -c -o flexdll_initer_cygwin.o flexdll_initer.c - -flexdll_initer_cygwin64.o: flexdll_initer.c - $(CYG64CC) -c -o flexdll_initer_cygwin64.o flexdll_initer.c - -flexdll_initer_mingw.o: flexdll_initer.c - $(MINCC) -c -o flexdll_initer_mingw.o flexdll_initer.c - -flexdll_initer_gnat.o: flexdll_initer.c - gcc -c -o flexdll_initer_gnat.o flexdll_initer.c - -flexdll_initer_mingw64.o: flexdll_initer.c - $(MIN64CC) -c -o flexdll_initer_mingw64.o flexdll_initer.c +flexdll_initer_gnat.o flexdll_gnat.o: flexdll.h flexdll.c flexdll_initer.c flexlink.exe + ./flexlink -v -install -o . -chain gnat demo_msvc: flexlink.exe flexdll_msvc.obj flexdll_initer_msvc.obj diff --git a/cmdline.ml b/cmdline.ml index 1ce4404..ea0a219 100644 --- a/cmdline.ml +++ b/cmdline.ml @@ -13,6 +13,8 @@ let underscore = ref true let machine : [ `x86 | `x64 ] ref = ref `x86 +let runtime_objects_dir = ref "" +let cc_prefix = ref "" let noexport = ref false let custom_crt = ref false let reexport_from_implibs = ref true @@ -36,7 +38,7 @@ let exts = ref [] let output_file = ref "" let exe_mode : [`DLL | `EXE | `MAINDLL] ref = ref `DLL let extra_args = ref [] -let mode : [`NORMAL | `DUMP | `PATCH] ref = ref `NORMAL +let mode : [`NORMAL | `DUMP | `PATCH | `INSTALL] ref = ref `NORMAL let defexports = ref [] let noentry = ref false let use_cygpath = ref true @@ -210,6 +212,15 @@ let specs = [ "-U", Arg.String (fun _ -> ()), " (Ignored)"; + "-install", Arg.Unit (fun () -> mode := `INSTALL), + " Compile runtime support file for the selected toolchain"; + + "-cc-prefix", Arg.Set_string cc_prefix, + " Add an explicit directory or a prefix in front of the C compiler (cl / gcc) and other tools"; + + "-runtime-objects", Arg.Set_string runtime_objects_dir, + " Specify in which directory the flexdll runtime objects are found"; + "--", Arg.Rest (fun s -> extra_args := s :: !extra_args), " Following arguments are passed verbatim to the linker"; ] diff --git a/reloc.ml b/reloc.ml index 8a04e41..e38a887 100644 --- a/reloc.ml +++ b/reloc.ml @@ -17,7 +17,9 @@ let search_path = ref [] let default_libs = ref [] let gcc = ref "gcc" +let cl = ref "cl" let objdump = ref "objdump" +let link = ref "link" let is_crt_lib = function | "LIBCMT" @@ -31,6 +33,10 @@ let flexdir = with Not_found -> Filename.dirname Sys.executable_name +let runtime_objects_dir = + if !runtime_objects_dir = "" then flexdir + else !runtime_objects_dir + let ext_obj () = if !toolchain = `MSVC || !toolchain = `MSVC64 then ".obj" else ".o" @@ -1018,7 +1024,8 @@ let build_dll link_exe output_file files exts extra_args = with the Windows 7 SDK in 64-bit mode. *) Printf.sprintf - "link /nologo %s%s%s%s%s /implib:%s /out:%s /subsystem:%s %s %s %s" + "%s /nologo %s%s%s%s%s /implib:%s /out:%s /subsystem:%s %s %s %s" + !link (if !verbose >= 2 then "/verbose " else "") (if link_exe = `EXE then "" else "/dll ") (if main_pgm then "" else "/export:symtbl /export:reloctbl ") @@ -1198,6 +1205,7 @@ let remove_duplicate_paths paths = let setup_toolchain () = let mingw_libs pre = + let pre = if !cc_prefix = "" then pre else !cc_prefix in gcc := pre ^ "gcc"; objdump := pre ^ "objdump"; let rec get_lib_search_dirs input = @@ -1229,24 +1237,39 @@ let setup_toolchain () = if !exe_mode = `EXE then default_libs := "crt2.o" :: !default_libs else default_libs := "dllcrt2.o" :: !default_libs in + let cygwin pre = + let pre = if !cc_prefix = "" then pre else !cc_prefix in + gcc := pre ^ "gcc"; + objdump := pre ^ "objdump"; + let lib_search_dirs = + [ + "/lib"; + "/lib/w32api"; + Filename.dirname (get_output1 ~use_bash:true (!gcc ^ " -print-libgcc-file-name")); + ] + in + search_path := !dirs @ lib_search_dirs; + if !verbose >= 1 then begin + print_endline "lib search dirs:"; + List.iter (Printf.printf " %s\n%!") lib_search_dirs; + end; + default_libs := ["-lkernel32"; "-luser32"; "-ladvapi32"; + "-lshell32"; "-lcygwin"; "-lgcc"] + in match !toolchain with | _ when !builtin_linker -> search_path := !dirs; add_flexdll_obj := false; noentry := true - | `CYGWIN | `CYGWIN64 -> - gcc := "gcc"; - objdump := "objdump"; - search_path := - !dirs @ - [ - "/lib"; - "/lib/w32api"; - Filename.dirname (get_output1 ~use_bash:true "gcc -print-libgcc-file-name"); - ]; - default_libs := ["-lkernel32"; "-luser32"; "-ladvapi32"; - "-lshell32"; "-lcygwin"; "-lgcc"] + | `CYGWIN -> + cygwin Version.cygwin_prefix + | `CYGWIN64 -> + cygwin Version.cygwin64_prefix | `MSVC | `MSVC64 -> + if !cc_prefix <> "" then begin + cl := !cc_prefix ^ "cl"; + link := !cc_prefix ^ "link"; + end; search_path := !dirs @ parse_libpath (try Sys.getenv "LIB" with Not_found -> ""); if not !custom_crt then @@ -1258,17 +1281,19 @@ let setup_toolchain () = | `GNAT -> (* This is a plain copy of the mingw version, but we do not change the prefix and use "gnatls" to compute the include dir. *) - search_path := - !dirs @ - [ - Filename.dirname (get_output1 (!gcc ^ " -print-libgcc-file-name")); - read_gnatls (); - ]; - default_libs := - ["-lmingw32"; "-lgcc"; "-lmoldname"; "-lmingwex"; "-lmsvcrt"; - "-luser32"; "-lkernel32"; "-ladvapi32"; "-lshell32" ]; - if !exe_mode = `EXE then default_libs := "crt2.o" :: !default_libs - else default_libs := "dllcrt2.o" :: !default_libs + gcc := !cc_prefix ^ "gcc"; + objdump := !cc_prefix ^ "objdump"; + search_path := + !dirs @ + [ + Filename.dirname (get_output1 (!gcc ^ " -print-libgcc-file-name")); + read_gnatls (); + ]; + default_libs := + ["-lmingw32"; "-lgcc"; "-lmoldname"; "-lmingwex"; "-lmsvcrt"; + "-luser32"; "-lkernel32"; "-ladvapi32"; "-lshell32" ]; + if !exe_mode = `EXE then default_libs := "crt2.o" :: !default_libs + else default_libs := "dllcrt2.o" :: !default_libs | `LIGHTLD -> search_path := !dirs @@ -1300,18 +1325,13 @@ let compile_if_needed file = let cmd = match !toolchain with | `MSVC | `MSVC64 -> Printf.sprintf - "cl /c /MD /nologo /Fo%s %s %s%s" + "%s /c /MD /nologo /Fo%s %s %s%s" + !cl (Filename.quote tmp_obj) (mk_dirs_opt "/I") file pipe - | `CYGWIN | `CYGWIN64 -> - Printf.sprintf - "gcc -c -o %s %s %s" - (Filename.quote tmp_obj) - (mk_dirs_opt "-I") - file - | `MINGW | `MINGW64 | `GNAT -> + | `CYGWIN | `CYGWIN64 | `MINGW | `MINGW64 | `GNAT -> Printf.sprintf "%s -c -o %s %s %s" !gcc @@ -1329,6 +1349,16 @@ let compile_if_needed file = end else file +let toolchain_suffix () = + match !toolchain with + | `MSVC -> "msvc.obj" + | `MSVC64 -> "msvc64.obj" + | `CYGWIN -> "cygwin.o" + | `CYGWIN64 -> "cygwin64.o" + | `MINGW64 -> "mingw64.o" + | `GNAT -> "gnat.o" + | `MINGW | `LIGHTLD -> "mingw.o" + let dump fn = let fn = find_file fn in Printf.printf "*** %s:\n" fn; @@ -1349,20 +1379,13 @@ let dump fn = let all_files () = let files = List.rev (List.map compile_if_needed !files) in let f obj = - let fn = Filename.concat flexdir obj in + let fn = Filename.concat runtime_objects_dir obj in (* Allow the obj files to be stored in a different location *) if file_exists fn <> None then fn else obj in - let tc = match !toolchain with - | `MSVC -> "msvc.obj" - | `MSVC64 -> "msvc64.obj" - | `CYGWIN -> "cygwin.o" - | `CYGWIN64 -> "cygwin64.o" - | `MINGW64 -> "mingw64.o" - | `GNAT -> "gnat.o" - | `MINGW | `LIGHTLD -> "mingw.o" in + let tc = toolchain_suffix () in if !exe_mode <> `DLL then if !add_flexdll_obj then f ("flexdll_" ^ tc) :: files else files @@ -1370,6 +1393,41 @@ let all_files () = if !noentry then files else f ("flexdll_initer_" ^ tc) :: files +let install file = + let target = Filename.concat !output_file file ^ "_" ^ toolchain_suffix () in + let target = Filename.quote (if !use_cygpath then cygpath1 target else target) in + let src = Filename.quote (Filename.concat flexdir file ^ ".c") in + let call_gcc extra = + Printf.sprintf + "%s -c %s -o %s %s" + !gcc + extra + target + src + in + let call_cl extra = + Printf.sprintf + "%s /DMSVC %s /c /MD /nologo -D_CRT_SECURE_NO_DEPRECATE /GS- /Fo%s %s" + !cl + extra + target + src + in + let cmd = + match !toolchain with + | `MSVC -> call_cl "" + | `MSVC64 -> call_cl "/DMSVC64" + | `CYGWIN | `CYGWIN64 -> call_gcc "-DCYGWIN" + | `MINGW | `MINGW64 -> call_gcc "-DMINGW" + | `GNAT -> call_gcc "" + | `LIGHTLD -> failwith "Compilation of C code is not supported for this toolchain" + in + if !verbose >= 1 || !dry_mode then Printf.printf "+ %s\n%!" cmd; + if not !dry_mode && Sys.command cmd <> 0 + then + failwith (Printf.sprintf "Error while compiling %s.c" file) + + let main () = parse_cmdline (); setup_toolchain (); @@ -1408,6 +1466,9 @@ let main () = (String.concat " " (List.map Filename.quote (List.rev !extra_args))) | `PATCH -> patch_output !output_file + | `INSTALL -> + install "flexdll"; + install "flexdll_initer" let () = try main ()