Commit 89274638 authored by Bas Lijnse's avatar Bas Lijnse

Added support for running additional linkers on linux

parent 33f86dd5
This diff is collapsed.
......@@ -7,4 +7,6 @@ IF_MACOSX macosx not_macosx :== not_macosx
DirSeparator:=='/'
DirSeparatorString:=="/"
TempDir :== "/tmp"
application_path :: !{#Char} -> {#Char}
implementation module PmCleanSystem
import StdEnv,StdMisc
import StdEnv,StdMisc,StdMaybe
from Directory import pd_StringToPath,getFileInfo,createDirectory,::Path,::FileInfo{pi_fileInfo},::PI_FileInfo{isDirectory},::DirError(..)
import UtilStrictLists
from Platform import DirSeparatorString
import StdPathname
from PmTypes import ::CodeGenOptions(..),::Processor,::ApplicationOptions(..),::Output(..),::LinkMethod,::ModuleDirAndName(..)
import PmTypes
from PmCompilerOptions import ::CompilerOptions(..),::ListTypes(..),instance == ListTypes
from PmPath import ModuleDirAndNameToABCSystemPathname,ModuleDirAndNameToObjSystemPathname
import PmCallBack
from PmParse import IsTypeSpec,IsImportError20
from linkargs import ReadLinkErrors,WriteLinkOpts,:: LinkInfo`(..),:: LPathname
from Platform import TempDir
tooltempdir =: TempDir
:: CompileOrCheckSyntax = SyntaxCheck | Compilation
......@@ -365,6 +369,7 @@ finish_code_generator process_handle {scg_abc_path,scg_path_without_suffix,scg_s
ps)
= (exit_code==0, ps)
import StdDebug, StdMisc
Link :: !String !(WindowFun *GeneralSt) !Pathname !ApplicationOptions
!Pathname !(List Pathname) !(List Pathname) !(List Pathname) !Bool !Bool !Bool !Bool !String
!Bool !String !Pathname !String !Processor !Bool !*GeneralSt
......@@ -388,70 +393,119 @@ Link linker winfun path
# (options_file_ok,ps) = accFiles (write_options_file optionspathname flags hs ss initial_heap_size heap_size_multiple minheap use_64_bit_processor) ps
| not options_file_ok
= (winfun ["Linker error: Could not write the options object file: "+++optionspathname] ps,False)
# object_paths = [optionspathname : StrictListToList (RemoveDup object_file_names)]
# temp_file_name = "/tmp/linkerXXXXXX" +++ "\0" // +++ because modified by mkstemp
# fd = mkstemp temp_file_name
| fd== -1
= abort "mkstemp failed"
# r = close fd
| r== -1
= abort "close failed"
# linker_args = [temp_file_name:object_paths]
# (argv,args_memory) = make_argv [linker:linker_args]
# linker_pid = fork
| linker_pid<0
= abort "fork failed"
| linker_pid==0
| execv (linker+++"\0") argv<0
= abort "execv failed"
= abort "execution continued after execv"
# (w_pid,status) = wait_pid linker_pid 0
| w_pid <> -1 && w_pid<>linker_pid
= abort "waitpid failed"
# result = (status bitand 0xff00) >> 8
# wtermsig = status bitand 0x7f
| wtermsig<>0
= abort "linker exited abnormally"
| free args_memory<0
= abort "free failed"
# link_ok = result>=0
| not link_ok
# use_optimizing_linker_and_gcc = is_optimizing_linker linker
| use_optimizing_linker_and_gcc
//First call the optimizing linker to generate an intermediate optimized object file which is then passed to gcc
# object_paths = [optionspathname : StrictListToList (RemoveDup object_file_names)]
# temp_file_name = "/tmp/linkerXXXXXX" +++ "\0" // +++ because modified by mkstemp
# fd = mkstemp temp_file_name
| fd== -1
= abort "mkstemp failed"
# r = close fd
| r== -1
= abort "close failed"
//Call optimized linker
# linker_args = [temp_file_name:object_paths]
# (argv,args_memory) = make_argv [linker:linker_args]
# linker_pid = fork
| linker_pid<0
= abort "fork failed"
| linker_pid==0
| execv (linker+++"\0") argv<0
= abort "execv failed"
= abort "execution continued after execv"
# (w_pid,status) = wait_pid linker_pid 0
| w_pid <> -1 && w_pid<>linker_pid
= abort "waitpid failed"
# result = (status bitand 0xff00) >> 8
# wtermsig = status bitand 0x7f
| wtermsig<>0
= abort "linker exited abnormally"
| free args_memory<0
= abort "free failed"
# link_ok = result>=0
| not link_ok
| unlink (temp_file_name+++"\0")<>0
= (ps,link_ok)
= (ps,link_ok)
//Call gcc
# ld_args = ["-o",path,temp_file_name:StrictListToList (Append library_file_names "-lm")]
# ld = "/usr/bin/gcc"
# (argv,args_memory) = make_argv [ld,"-s":ld_args]
# ld_pid = fork
| ld_pid<0
= abort "fork failed"
| ld_pid==0
| execv (ld+++"\0") argv<0
= abort "execv failed"
= abort "execution continued after execv"
| free args_memory<0
= abort "free failed"
# (w_pid,status) = wait_pid ld_pid 0
| w_pid <> -1 && w_pid<>ld_pid
= abort "waitpid failed"
# result = (status bitand 0xff00) >> 8
# wtermsig = status bitand 0x7f
| wtermsig<>0
= abort "ld exited abnormally"
# link_ok = result>=0
| unlink (temp_file_name+++"\0")<>0
= (ps,link_ok)
= (ps,link_ok)
# ld_args = ["-o",path,temp_file_name:StrictListToList (Append library_file_names "-lm")]
# ld = "/usr/bin/gcc"
# (argv,args_memory) = make_argv [ld,"-s":ld_args]
# ld_pid = fork
| ld_pid<0
= abort "fork failed"
| ld_pid==0
| execv (ld+++"\0") argv<0
= abort "execv failed"
= abort "execution continued after execv"
| free args_memory<0
= abort "free failed"
# (w_pid,status) = wait_pid ld_pid 0
| w_pid <> -1 && w_pid<>ld_pid
= abort "waitpid failed"
# result = (status bitand 0xff00) >> 8
# wtermsig = status bitand 0x7f
| wtermsig<>0
= abort "ld exited abnormally"
# link_ok = result>=0
| unlink (temp_file_name+++"\0")<>0
= (ps,link_ok)
| otherwise
//Call other/additional linker
# linkopts =
{ exe_path = path
, res_path = resource_path
, open_console = o <> NoConsole
, static_link = static
, gen_relocs = gen_relocs
, gen_linkmap = gen_linkmap
, link_resources = link_resources
, object_paths = optionspathname :! (RemoveDup object_file_names)
, dynamic_libs = RemoveDup library_file_names
, static_libs = RemoveDup static_libraries
, stack_size = ss
, gen_dll = gen_dll
, dll_names = dll_syms
, dynamics_path = startupdir +++. DirSeparatorString +++. dynlstr
, lib_name_obj_path = MakeFullPathname tooltempdir "lib_name.o"
}
# linkoptspath = MakeFullPathname tooltempdir "linkopts"
# linkerrspath = MakeFullPathname tooltempdir "linkerrs"
# (err,ps) = accFiles (WriteLinkOpts linkoptspath linkopts) ps
| isJust err
= (winfun (fromJust err) ps,False)
# linker_args = ["-I",linkoptspath,"-O",linkerrspath]
# (argv,args_memory) = make_argv [linker:linker_args]
# linker_pid = fork
| linker_pid<0
= abort "fork failed"
| linker_pid==0
| execv (linker+++"\0") argv<0
= abort "execv failed"
= abort "execution continued after execv"
# (w_pid,status) = wait_pid linker_pid 0
| w_pid <> -1 && w_pid<>linker_pid
= abort "waitpid failed"
# result = (status bitand 0xff00) >> 8
# wtermsig = status bitand 0x7f
| wtermsig<>0
= abort "linker exited abnormally"
| free args_memory<0
= abort "free failed"
# link_ok = result>=0
= (ps,link_ok)
is_optimizing_linker :: !{#Char} -> Bool
is_optimizing_linker name
# len = size name
= len >= 14 && (name % (len - 14, len) == "lib/exe/linker")
DelayEventLoop :: !.ps -> .ps
DelayEventLoop ps
= ps
......
......@@ -8,7 +8,7 @@ set_return_code_world i world = IF_INT_64_OR_32 (set_return_code_world64 i world
set_return_code_world64 :: !Int !*World -> *World
set_return_code_world64 i world = code {
pushI 0
pushLc _return_code
pushLc return_code
:xxx
pop_b 3
| mov dword ptr [rbx+r10],eax
......@@ -25,7 +25,7 @@ set_return_code_world32 i world = code {
fill_a 0 1
pop_a 1
pushI 0
pushLc _return_code
pushLc return_code
:xxx
pop_b 3
| mov (%esp),%edx
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment