Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support compilation of shared library (DLL) for Windows #160

Merged
merged 7 commits into from
May 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/workflows/ci-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,17 @@ jobs:
os:
- ubuntu-latest
- macOS-latest
- windows-latest
arch:
- x64
group:
- Integration
steps:
- uses: actions/checkout@v2
- uses: KyleMayes/install-llvm-action@v2
with:
version: "17"
if: matrix.os == 'windows-latest'
- uses: julia-actions/setup-julia@latest
with:
version: ${{ matrix.version }}
Expand Down
5 changes: 5 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ jobs:
os:
- ubuntu-latest
- macOS-latest
- windows-latest
arch:
- x64
group:
Expand All @@ -34,6 +35,10 @@ jobs:
os: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: KyleMayes/install-llvm-action@v2
with:
version: "17"
if: matrix.os == 'windows-latest'
- uses: julia-actions/setup-julia@latest
with:
version: ${{ matrix.version }}
Expand Down
30 changes: 24 additions & 6 deletions src/StaticCompiler.jl
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ include("interpreter.jl")
include("target.jl")
include("pointer_warning.jl")
include("quirks.jl")
include("dllexport.jl")

fix_name(f::Function) = fix_name(string(nameof(f)))
fix_name(s) = String(GPUCompiler.safe_name(s))
Expand Down Expand Up @@ -125,6 +126,7 @@ function compile_executable(funcs::Union{Array,Tuple}, path::String=pwd(), name=
nativetype || @warn "Return type `$rt` of `$f$types` does not appear to be a native type. Consider returning only a single value of a native machine type (i.e., a single float, int/uint, bool, or pointer). \n\nIgnoring this warning may result in Undefined Behavior!"

generate_executable(funcs, path, name, filename; demangle, cflags, target, llvm_to_clang, kwargs...)
Sys.iswindows() && (filename *= ".exe")
joinpath(abspath(path), filename)
end

Expand Down Expand Up @@ -187,6 +189,7 @@ function compile_shlib(funcs::Union{Array,Tuple}, path::String=pwd();
demangle = true,
cflags = ``,
target::StaticTarget=StaticTarget(),
llvm_to_clang = Sys.iswindows(),
kwargs...
)
for func in funcs
Expand All @@ -200,7 +203,7 @@ function compile_shlib(funcs::Union{Array,Tuple}, path::String=pwd();
nativetype || @warn "Return type `$rt` of `$f$types` does not appear to be a native type. Consider returning only a single value of a native machine type (i.e., a single float, int/uint, bool, or pointer). \n\nIgnoring this warning may result in Undefined Behavior!"
end

generate_shlib(funcs, path, filename; demangle, cflags, target, kwargs...)
generate_shlib(funcs, path, filename; demangle, cflags, target, llvm_to_clang, kwargs...)

joinpath(abspath(path), filename * "." * Libdl.dlext)
end
Expand Down Expand Up @@ -325,17 +328,18 @@ function generate_executable(funcs::Union{Array,Tuple}, path=tempname(), name=fi
if llvm_to_clang # (required on Windows)
# Use clang (llc) to generate an executable from the LLVM IR
cclang = if Sys.iswindows()
`cmd \c clang` # Not clear if the `cmd \c` is necessary
exec_path *= ".exe"
`clang`
elseif Sys.isapple()
`clang`
else
clang()
end
run(`$cclang -Wno-override-module $wrapper_path $obj_or_ir_path -o $exec_path`)
run(`$cclang -Wno-override-module $wrapper_path $obj_or_ir_path -o $exec_path`)
else
run(`$cc $wrapper_path $cflags $obj_or_ir_path -o $exec_path`)
end

# Clean up
rm(wrapper_path)
end
Expand Down Expand Up @@ -391,6 +395,7 @@ function generate_shlib(funcs::Union{Array,Tuple}, path::String=tempname(), file
demangle = true,
cflags = ``,
target::StaticTarget=StaticTarget(),
llvm_to_clang::Bool = Sys.iswindows(),
kwargs...
)
if !isnothing(target.platform)
Expand All @@ -399,15 +404,28 @@ function generate_shlib(funcs::Union{Array,Tuple}, path::String=tempname(), file
lib_path = joinpath(path, "$filename.$(Libdl.dlext)")
end

_, obj_path = generate_obj(funcs, path, filename; target, demangle, kwargs...)
_, obj_or_ir_path = generate_obj(funcs, path, filename; demangle, target, emit_llvm_only=llvm_to_clang, kwargs...)
# Pick a Clang
if !isnothing(target.compiler)
cc = `$(target.compiler)`
else
cc = Sys.isapple() ? `cc` : clang()
end
# Compile!
run(`$cc -shared $cflags $obj_path -o $lib_path `)
if llvm_to_clang # (required on Windows)
# Use clang (llc) to generate an executable from the LLVM IR
cclang = if Sys.iswindows()
add_dllexport(funcs, obj_or_ir_path; demangle)
`clang`
elseif Sys.isapple()
`clang`
else
clang()
end
run(`$cclang -shared -Wno-override-module $obj_or_ir_path -o $lib_path`)
else
run(`$cc -shared $cflags $obj_or_ir_path -o $lib_path `)
end

path, name
end
Expand Down
11 changes: 11 additions & 0 deletions src/dllexport.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
function add_dllexport(funcs, ir_path; demangle=true)
ir = read(ir_path, String)

for (f, _) in funcs
name_f = (demangle ? "" : "julia_") * fix_name(f)
pattern = Regex("^define(.*?@$name_f\\()", "m")
ir = replace(ir, pattern => s"define dllexport\1")
end

write(ir_path, ir)
end
11 changes: 8 additions & 3 deletions test/testintegration.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ if VERSION >= v"1.9"
buf = AllocBuffer(MallocVector, sizeof(Float64) * N)
s = 0.0
for i ∈ 1:N
# some excuse to reuse the same memory a bunch of times
# some excuse to reuse the same memory a bunch of times
@no_escape buf begin
v = @alloc(Float64, N)
v .= i
Expand All @@ -24,7 +24,7 @@ if VERSION >= v"1.9"

path = compile_shlib(bumper_test, (Int,), "./")
ptr = Libdl.dlopen(path, Libdl.RTLD_LOCAL)

fptr = Libdl.dlsym(ptr, "bumper_test")

@test bumper_test(8) == @ccall($fptr(8::Int)::Float64)
Expand Down Expand Up @@ -303,7 +303,12 @@ end
catch e
@info "maybe_throw: task failed sucessfully!"
end
@test status === -1
if Sys.iswindows()
@info "maybe_throw: task doesn't fail on Windows."
@test status.exitcode == 0
else
@test status === -1
end
end

## --- Test interop
Expand Down
Loading