From 72a90e14b6c28e06ec0941f9875c93e910676a6e Mon Sep 17 00:00:00 2001 From: Daizu Date: Sun, 19 May 2024 00:00:27 +0900 Subject: [PATCH 1/6] Add dllexport.jl --- src/StaticCompiler.jl | 30 ++++++++++++++++++++++++------ src/dllexport.jl | 11 +++++++++++ 2 files changed, 35 insertions(+), 6 deletions(-) create mode 100644 src/dllexport.jl diff --git a/src/StaticCompiler.jl b/src/StaticCompiler.jl index 38547fe..90e3404 100644 --- a/src/StaticCompiler.jl +++ b/src/StaticCompiler.jl @@ -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)) @@ -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 @@ -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 @@ -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 @@ -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 @@ -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) @@ -399,7 +404,7 @@ 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)` @@ -407,7 +412,20 @@ function generate_shlib(funcs::Union{Array,Tuple}, path::String=tempname(), file 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 diff --git a/src/dllexport.jl b/src/dllexport.jl new file mode 100644 index 0000000..b957e7b --- /dev/null +++ b/src/dllexport.jl @@ -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 \ No newline at end of file From 8ad178a44602eec90ee0f0aff36ad4a01af791eb Mon Sep 17 00:00:00 2001 From: Daizu Date: Sun, 19 May 2024 09:29:10 +0900 Subject: [PATCH 2/6] Update tests for Windows --- test/runtests.jl | 6 +++++- test/testintegration.jl | 11 ++++++++--- test/testintegration_windows.jl | 17 +++++++++++++++++ 3 files changed, 30 insertions(+), 4 deletions(-) create mode 100644 test/testintegration_windows.jl diff --git a/test/runtests.jl b/test/runtests.jl index 542659c..cf2964c 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -21,5 +21,9 @@ if GROUP == "Core" || GROUP == "All" end if GROUP == "Integration" || GROUP == "All" - include("testintegration.jl") + if Sys.iswindows() + include("testintegration_windows.jl") + else + include("testintegration.jl") + end end diff --git a/test/testintegration.jl b/test/testintegration.jl index 3422e63..e52a154 100644 --- a/test/testintegration.jl +++ b/test/testintegration.jl @@ -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 @@ -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) @@ -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 in Windows." + @test status.exitcode == 0 + else + @test status === -1 + end end ## --- Test interop diff --git a/test/testintegration_windows.jl b/test/testintegration_windows.jl new file mode 100644 index 0000000..3e6a887 --- /dev/null +++ b/test/testintegration_windows.jl @@ -0,0 +1,17 @@ +# Currently, `StaticTools.stderrp()` used in `test/scripts` doesn't work in Windows. +# This temporary file deletes `stderrp()` and run tests. + +mkpath("scripts_windows") + +for file in readdir("scripts") + script = read("scripts/$file", String) + script = replace(script, "printf(stderrp(), " => "printf(") + write("scripts_windows/$file", script) +end + +script = read("testintegration.jl", String) +script = replace(script, "testpath/scripts/" => "testpath/scripts_windows/") + +include_string(Main, script) + +rm("scripts_windows"; recursive=true) \ No newline at end of file From 489689a06d14b8fe599a5d33db4627e2283e2884 Mon Sep 17 00:00:00 2001 From: Daizu Date: Sun, 19 May 2024 10:38:13 +0900 Subject: [PATCH 3/6] change comments --- test/testintegration.jl | 2 +- test/testintegration_windows.jl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/testintegration.jl b/test/testintegration.jl index e52a154..d2a98da 100644 --- a/test/testintegration.jl +++ b/test/testintegration.jl @@ -304,7 +304,7 @@ end @info "maybe_throw: task failed sucessfully!" end if Sys.iswindows() - @info "maybe_throw: task doesn't fail in Windows." + @info "maybe_throw: task doesn't fail on Windows." @test status.exitcode == 0 else @test status === -1 diff --git a/test/testintegration_windows.jl b/test/testintegration_windows.jl index 3e6a887..7ac95e5 100644 --- a/test/testintegration_windows.jl +++ b/test/testintegration_windows.jl @@ -1,4 +1,4 @@ -# Currently, `StaticTools.stderrp()` used in `test/scripts` doesn't work in Windows. +# Currently, `StaticTools.stderrp()` used in `test/scripts` doesn't work on Windows. # This temporary file deletes `stderrp()` and run tests. mkpath("scripts_windows") From 76bff06fbac59d74bcb647fb1e097c31503f2f4e Mon Sep 17 00:00:00 2001 From: Daizu Date: Sun, 19 May 2024 11:05:53 +0900 Subject: [PATCH 4/6] Use llvm action --- .github/workflows/ci.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3dc141f..499223c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,6 +24,7 @@ jobs: os: - ubuntu-latest - macOS-latest + - windows-latest arch: - x64 group: @@ -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 }} From a57094c765bfb32bdf3970f33b77fcd53120daca Mon Sep 17 00:00:00 2001 From: Daizu Date: Sun, 19 May 2024 11:12:39 +0900 Subject: [PATCH 5/6] Use llvm action (Integration) --- .github/workflows/ci-integration.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/ci-integration.yml b/.github/workflows/ci-integration.yml index beb16c1..544b0a4 100644 --- a/.github/workflows/ci-integration.yml +++ b/.github/workflows/ci-integration.yml @@ -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 }} From 7d53475cc263498764deb72e1d400fb3ec90394a Mon Sep 17 00:00:00 2001 From: Daizu Date: Tue, 21 May 2024 05:41:00 +0900 Subject: [PATCH 6/6] Delete `testintegration_windows.jl` --- test/runtests.jl | 6 +----- test/testintegration_windows.jl | 17 ----------------- 2 files changed, 1 insertion(+), 22 deletions(-) delete mode 100644 test/testintegration_windows.jl diff --git a/test/runtests.jl b/test/runtests.jl index cf2964c..542659c 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -21,9 +21,5 @@ if GROUP == "Core" || GROUP == "All" end if GROUP == "Integration" || GROUP == "All" - if Sys.iswindows() - include("testintegration_windows.jl") - else - include("testintegration.jl") - end + include("testintegration.jl") end diff --git a/test/testintegration_windows.jl b/test/testintegration_windows.jl deleted file mode 100644 index 7ac95e5..0000000 --- a/test/testintegration_windows.jl +++ /dev/null @@ -1,17 +0,0 @@ -# Currently, `StaticTools.stderrp()` used in `test/scripts` doesn't work on Windows. -# This temporary file deletes `stderrp()` and run tests. - -mkpath("scripts_windows") - -for file in readdir("scripts") - script = read("scripts/$file", String) - script = replace(script, "printf(stderrp(), " => "printf(") - write("scripts_windows/$file", script) -end - -script = read("testintegration.jl", String) -script = replace(script, "testpath/scripts/" => "testpath/scripts_windows/") - -include_string(Main, script) - -rm("scripts_windows"; recursive=true) \ No newline at end of file