# Relocatable app workflow with PackageCompiler

**URL:** <https://discourse.julialang.org/t/relocatable-app-workflow-with-packagecompiler/65058>\
**Category:** General Usage\
**Tags:** package, package-compiler, application, pkgtemplates\
**Created:** [July 21, 2021, 6:54pm UTC](https://discourse.julialang.org/t/relocatable-app-workflow-with-packagecompiler/65058 "2021-07-21T18:54:26Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![connormeaton](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/connormeaton/32/27120_2.png) [@connormeaton](https://discourse.julialang.org/u/connormeaton)\
**Post date:** [July 21, 2021, 6:54pm UTC](https://discourse.julialang.org/t/relocatable-app-workflow-with-packagecompiler/65058/1 "2021-07-21T18:54:26Z")

</div>

Thanks to the help of @oheil, @mkitti, and @kristoffer.carlsson, I have compiled a julia app using PackageCompiler and PkgTemplate that accepts a file path as a command line argument and prints it out as a dataframe.

Here is my workflow:

```julia
$ julia
$ using PkgTemplates
$ t = Template()
$ t(“demoApp”)
$ ] activate <path listed in the previous command >
$ ] add DataFrames, CSV, 
$ cd(“<path listed above for package>”)
$ Using demoApp

- Add Artifacts.toml file to project directory. PkgTemplates does not include this, but it is necessary.

- Add source code to the directory at ~/.julia/dev/demoApp/src/demoApp.jl. 

$ create_app("../demoApp","demoAppCompiled";force=true)

TO RUN:

$ ~/.julia/dev/demoApp/demoAppCompiled/bin/demoApp test.txt

2×3 DataFrame
 Row │ a b c
     │ Int64 Int64 Int64
─────┼─────────────────────
   1 │ 1 2 3
   2 │ 4 5 6

```

I grabbed the `Artifacts.toml` file from here:  
[https://github.com/JuliaLang/PackageCompiler.jl/blob/master/examples/MyApp/Artifacts.toml](https://github.com/JuliaLang/PackageCompiler.jl/blob/master/examples/MyApp/Artifacts.toml)

My source code for the app looks like this:

```julia
module demoApp

using DataFrames, CSV

using Pkg.Artifacts

fooifier_path() = joinpath(artifact"fooifier", "bin", "fooifier" * (Sys.iswindows() ? ".exe" : ""))

function julia_main()
    try
        real_main()
    catch
        Base.invokelatest(Base.display_error, Base.catch_stack())
        return 1
    end
    return 0
end

function real_main()
    df = CSV.read(string(ARGS[1]), DataFrame);
    println(df)
    return
end

if abspath(PROGRAM_FILE) == @ __FILE__
    real_main()
end

end

```

It compiles properly and I get a directory `demoAppCompiled/` with the appropriate contents. I then run `demoAppCompiled/bin/demoApp test.txt` on my machine and it works perfectly.

Now, I’ve zipped `demoAppCompiled/`, moved the zipped object to a new location on my machine, unzipped, and tried to run the same command. It breaks with this error:

```julia
(base) connor@connors-MacBook-Pro:~/Downloads/rppApp$ rppgAppCompiled/bin/rppgApp workingTest.csv 
fatal: error thrown and no exception handler available.
InitError(mod=:OpenSpecFun_jll, error=ErrorException("could not load library "/Users/connor/Downloads/rppApp/rppgAppCompiled/artifacts/083301655942999198605bee77f89f1d41bf820e/lib/libopenspecfun.1.4.dylib"
dlopen(/Users/connor/Downloads/rppApp/rppgAppCompiled/artifacts/083301655942999198605bee77f89f1d41bf820e/lib/libopenspecfun.1.4.dylib, 1): no suitable image found. Did find:
	/Users/connor/Downloads/rppApp/rppgAppCompiled/artifacts/083301655942999198605bee77f89f1d41bf820e/lib/libopenspecfun.1.4.dylib: code signature in (/Users/connor/Downloads/rppApp/rppgAppCompiled/artifacts/083301655942999198605bee77f89f1d41bf820e/lib/libopenspecfun.1.4.dylib) not valid for use in process using Library Validation: library load disallowed by system policy"))
jl_errorf at /usr/local/opt/julia/lib/julia/libjulia-internal.dylib (unknown line)
jl_load_dynamic_library at /usr/local/opt/julia/lib/julia/libjulia-internal.dylib (unknown line)
YY.dlopenYY.3 at /Users/connor/Downloads/rppApp/rppgAppCompiled/bin/rppgApp.dylib (unknown line)
dlopen at ./libdl.jl:114
unknown function (ip: 0x109301971)
jl_apply_generic at /usr/local/opt/julia/lib/julia/libjulia-internal.dylib (unknown line)
__init__ at /Users/connor/Downloads/rppApp/rppgAppCompiled/bin/rppgApp.dylib (unknown line)
jl_apply_generic at /usr/local/opt/julia/lib/julia/libjulia-internal.dylib (unknown line)
jl_module_run_initializer at /usr/local/opt/julia/lib/julia/libjulia-internal.dylib (unknown line)
_julia_init at /usr/local/opt/julia/lib/julia/libjulia-internal.dylib (unknown line)
main at /Users/connor/Downloads/rppApp/rppgAppCompiled/bin/rppgApp (unknown line)

```

I see there are some nice docs describing that my problem is that my app is not relocatable. The docs are here:  
[https://julialang.github.io/PackageCompiler.jl/dev/devdocs/relocatable\_part\_3/](https://julialang.github.io/PackageCompiler.jl/dev/devdocs/relocatable_part_3/)

However, it is unclear to me how to incorporate the suggestions in these into my workflow. They recommend using gcc and what not, but is there anyway to make my app work at any location and ultimately, on any machine, without leaving PackageCompiler?

Thank you.

---

<div class="post-metadata">

**Author:** ![oheil](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oheil/32/220745_2.png) [@oheil](https://discourse.julialang.org/u/oheil)\
**Post date:** [July 21, 2021, 7:20pm UTC](https://discourse.julialang.org/t/relocatable-app-workflow-with-packagecompiler/65058/2 "2021-07-21T19:20:12Z")

</div>

I have never done this, but my guess is, that it’s not about PackageCompiler but about Artifacts location:  
[http://pkgdocs.julialang.org/v1/artifacts/#Overriding-artifact-locations](http://pkgdocs.julialang.org/v1/artifacts/#Overriding-artifact-locations)

There are some examples with absolute paths, perhaps one can specify a relative path here, too. A relative path to the library would be relocatable.

But really, I am only guessing here, perhaps the others have experience with it and know how to do it.

---

<div class="post-metadata">

**Author:** ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)\
**Post date:** [July 22, 2021, 7:28am UTC](https://discourse.julialang.org/t/relocatable-app-workflow-with-packagecompiler/65058/3 "2021-07-22T07:28:00Z")

</div>

> [@connormeaton](#):
>
> ```julia
> "could not load library "/Users/connor/Downloads/rppApp/rppgAppCompiled/artifacts/083301655942999198605bee77f89f1d41bf820e/lib/libopenspecfun.1.4.dylib"
> dlopen(/Users/connor/Downloads/rppApp/rppgAppCompiled/artifacts/083301655942999198605bee77f89f1d41bf820e/lib/libopenspecfun.1.4.dylib, 1): no suitable image found. Did find:
> /Users/connor/Downloads/rppApp/rppgAppCompiled/artifacts/083301655942999198605bee77f89f1d41bf820e/lib/libopenspecfun.1.4.dylib: code signature in (/Users/connor/Downloads/rppApp/rppgAppCompiled/artifacts/083301655942999198605bee77f89f1d41bf820e/lib/libopenspecfun.1.4.dylib) not valid for use in process using Library Validation: library load disallowed by system policy"
> 
> ```

The error is about code signing and is specific to macOS.

If you google “not valid for use in process using Library Validation: library load disallowed by system policy”, you will find several work arounds ranging from disabling library validation to code signing.

Here are some links:

> <https://github.com/opencv/opencv/issues/15645>
>
> This is the first time to use opencv at Mac OS. I used homebrew to install openc…v in my Macbook, and all path search definitely correct in Xcode. I created a hello world in commandline tool project using C++ language not OBJC language. I could compile my opencv hello world, but it was broken in runtime, with showing the following logs:
> === logs ====
> dyld: Library not loaded: /usr/local/opt/opencv/lib/libopencv\_flann.4.1.dylib
> Referenced from: /Users/weibinwu/Library/Developer/Xcode/DerivedData/OpenCV-frdcgrfkxsvbyahjaonnyllerinn/Build/Products/Debug/OpenCV
> Reason: no suitable image found. Did find:
> /usr/local/opt/opencv/lib/libopencv\_flann.4.1.dylib: code signature in (/usr/local/opt/opencv/lib/libopencv\_flann.4.1.dylib) not valid for use in process using Library Validation: mapped file has no cdhash, completely unsigned? Code has to be at least ad-hoc signed.
> /usr/local/lib/libopencv\_flann.4.1.dylib: code signature in (/usr/local/lib/libopencv\_flann.4.1.dylib) not valid for use in process using Library Validation: mapped file has no cdhash, completely unsigned? Code has to be at least ad-hoc signed.
> /usr/local/Cellar/opencv/4.1.1\_2/lib/libopencv\_flann.4.1.1.dylib: code signature in (/usr/local/Cellar/opencv/4.1.1\_2/lib/libopencv\_flann.4.1.1.dylib) not valid for use in process using Library Validation: mapped file has no cdhash, completely unsigned? Code has to be at least ad-hoc signed.
> == logs ===
> 
> please could somebody help me out of this problem?

> **[Disable Library Validation Entitlement | Apple Developer Documentation](https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_security_cs_disable-library-validation)**
>
> A Boolean value that indicates whether the app loads arbitrary plug-ins or frameworks, without requiring code signing.

> The [Hardened Runtime](https://developer.apple.com/documentation/security/hardened_runtime) enables library validation by default. This security-hardening feature prevents a program from loading frameworks, plug-ins, or libraries unless they’re either signed by Apple or signed with the same Team ID as the main executable. The macOS dynamic linker ( `dyld` ) provides a detailed error message when the system prevents code from loading due to library validation. Use the `Disable Library Validation Entitlement` if your program loads plug-ins that are signed by other third-party developers.

Perhaps @giordano and @staticfloat know something more about how the artifacts are signed and how you might able to create a compatible signature.

---

<div class="post-metadata">

**Author:** ![connormeaton](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/connormeaton/32/27120_2.png) [@connormeaton](https://discourse.julialang.org/u/connormeaton)\
**Post date:** [July 22, 2021, 2:24pm UTC](https://discourse.julialang.org/t/relocatable-app-workflow-with-packagecompiler/65058/4 "2021-07-22T14:24:46Z")

</div>

Thanks. So you’re thinking this is a specific Mac issue and not necessarily related to the relocatable app documentation on PackageCompiler?

Theoretically, if I compile on a different OS with the same process, then it should work across platforms then?

---

<div class="post-metadata">

**Author:** ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)\
**Post date:** [July 22, 2021, 2:34pm UTC](https://discourse.julialang.org/t/relocatable-app-workflow-with-packagecompiler/65058/5 "2021-07-22T14:34:50Z")

</div>

As far as I know, the system image produced by PackageCompiler.jl is not cross-platform. The system image consists of code native to each platform. You cannot compile the system image on Linux or Windows and have it work on macOS.

---

<div class="post-metadata">

**Author:** ![connormeaton](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/connormeaton/32/27120_2.png) [@connormeaton](https://discourse.julialang.org/u/connormeaton)\
**Post date:** [July 22, 2021, 2:43pm UTC](https://discourse.julialang.org/t/relocatable-app-workflow-with-packagecompiler/65058/6 "2021-07-22T14:43:15Z")

</div>

Gotcha, I guess I didn’t have a proper understanding of PackageCompiler. So if I want it to run on multiple platforms, I should compile separately on multiple platforms?

Regarding the original problem, it sounds like its just a Mac issue. So if I repeat the compilation steps on a linux machine, there _in theory_ should be any problems?
