JuliaC feature request: strip off libuv when there's no IO

Using a shared libraries compiled by JuliaC seems to cause unexpected interactions with the IO of a host program, even when the shared library is purely numerical and does not perform IO. I think this is caused by Juila’s libuv for async IO. Here’s a short MWE, adapted from the official JuliaC examples. First, the Julia code to be compiled:

# libtest.jl
module LibTest

Base.@ccallable function jc_add_one(x::Cint)::Cint
    return x + 1
end

end # module

I compile it with

juliac --output-lib libjc_add_one.so --bundle jc_add_one --trim=safe --experimental --compile-ccallable libtest.jl

Next, I call the shared library from the following C program, which repeatedly reads stdin for integers and prints out the results after adding 1:

// ctest.c
#include <stdio.h>

int jc_add_one(int x); // to link against libjc_add_one.so

int main(void) {
    int i;
    while (!feof(stdin)) {
        if (scanf("%d", &i) == 1) {
            printf("%d\n", jc_add_one(i));
            fflush(stdout);
        }
        else {
            if (!feof(stdin))
                printf("invalid integer input!\n");
        }
    }
    return 0;
}

I compile it with

gcc ctest.c -o ctest -Ljc_add_one/lib -ljc_add_one -Wl,-rpath,jc_add_one/lib

I test it in the shell with a pipeline in Linux:

{ echo 1; sleep 1; echo 2; } | ./ctest

The output is

2
invalid integer input!
invalid integer input!
invalid integer input!
invalid integer input!
invalid integer input!
[5 million lines omitted]

The expected out is, e.g. as generated by a C program using i+1 instead of jc_add_one(i),

2
3

I’ve previously posted about issues with embedding Juila in C (on Discourse and Github), but I just noticed that the same libuv issue is also present with JuliaC. Would it be possible for future versions of JuliaC to strip off libuv when the compiled program / library does not perform IO? I’d like to “sneak” some Julia code into existing C/C++/Python projects for CLI tools with heavy use of pipes, without requiring my collaborators to adapt the IO aspects of the rest of the codebase.

I have Julia 1.12.1 x86_64-linux-gnu, GCC 15.2.1, and JuliaC installed from Pkg a few days ago (not sure how to print out its version).

P.S. the JuliaC version is v0.2.2.

This is probably not as simple as it may seem. Even when there is no IO in the form of printing going on, the async runtime of libuv is still used for task scheduling. As there is always at least one task, removing libuv is currently not possible.

1 Like

Type:

versioninfo()

at the Julia prompt (REPL).

I meant the version of JuliaC installed from pkg> app add JuliaC. This doesn’t show up in the output of pkg> st.

You can do app st:

(@v1.12) pkg> app st
[7d51a73a] ExplicitImports v1.13.0
  explicit-imports-jl ~/.julia/juliaup/julia-1.12.0-rc1+0.aarch64.apple.darwin14/bin/julia
[78c8a9bf] SearchablePDFs v0.1.0 `https://github.com/ericphanson/SearchablePDFs.jl#main`
  searchable-pdf ~/.julia/juliaup/julia-1.12.1+0.aarch64.apple.darwin14/bin/julia
[acedd4c2] JuliaC v0.2.2
  juliac ~/.julia/juliaup/julia-1.12.1+0.aarch64.apple.darwin14/bin/julia
1 Like