
@rajan.yadav has joined the channel

Hi all! Is there a way to set rpath for racket linux executables using ffi libs, so that there is no need to set LD_LIBRARY_PATH at target system?

I have not tried that, but it seems like it would work. There is not currently a mechanism in the Racket build process to do that automatically.

You could set CCFLAGS
when compiling, which would probably enable this.

@hazel You might be interested in this idea, which might allow you to get rid of the wrapper script on Nix.

@rajan.yadav I hope, I got the context right. You wanted to distribute an application written in Racket. A package uses a shared library (not part of the pacakage) and the problem is now to include the shared library when raco distribute
is used?

Including shared libs in distribution isn’t a problem. It can be done by using collects flags. The problem I am having is that executable isn’t using bundled shared libs without setting LD_LIBRARY_PATH on target machine. I have a requirement where setting LD_LIBRARY_PATH isn’t an option and must work without it out of the box

@samth thanks. I’ll try it out

I’ll look into this — I already planned on submitting a PR to nixpkgs when 8.1 is out

@hazel what is the wrapper script workaround?

#!/bin/sh
export LD_LIBRARY_PATH="what-you-want-it-to-be"
exec /path/to/actual/racket

’tis a real masterpiece of engineering

Lol I imagined a bunch of magical gcc flags being passed to raco :grinning:

@rajan.yadav to clarify, are you talking about something built with raco distribute
? If so, are you using define-runtime-path
to define the path you use to load the library?

@ryanc Yes. I am talking about something built with raco distribute
. And yes, I experimented with define-runtime-path
in my code . But ffi libs are used in sci/flomat package which doesn’t do that. I imagine define-runtime-path
should be used in that module (flomat) for it to work right ? Its a long shout but I can try modifying flomat’s code and see if that works.

I think define-runtime-path
would not work for flomat
, since it’s intended to be able to work with existing .so libraries in multiple places that are not known at compile time.

Yes, that is what I thought. Therefore my preference is to somehow hardwire lib search paths within executable. This is very trivial to do directly using gcc.

I am considering using https://docs.racket-lang.org/dynext/Linking.html?q=current-extension#%28def._%28%28lib._dynext%2Flink..rkt%29._current-extension-linker-flags%29%29\|https://docs.racket-lang.org/dynext/Linking.html?q=current-extension#%28def._%28%28lib._dynext%2Flink..rkt%[…]._current-extension-linker-flags%29%29 followed by https://docs.racket-lang.org/raco/exe.html?q=raco%20exe#%28def._%28%28lib._compiler%2Fembed..rkt%29._create-embedding-executable%29%29. But later is giving me new issues

Lets see how that goes

A few things about that: 1. raco exe
(which is the same as create-embedding-executable
) doesn’t call gcc
to create the executable. 2. “extensions” in the sense of current-extension-linker-flags
are not what flomat or other ffi-using libraries use.

Btw - I think dynext is a package for compiling/linking C files - so I don’t see the connection to the problem.

What if … define-runtime-path
is used in Rajan’s code with the BLAS/LAPACK he needs - wouldn’t flomat automatically pick the same instances up?

Yes, I think that would work.

Well, maybe. I’m not sure if the result of raco distribute
would put the so in a location that ffi-lib
would find by default.

flomat
could provide a way to specify that path, and then @rajan.yadav could use define-runtime-path
and then that mechanism.

The paths are exported as cblas-lib
and lapack-lib
. https://github.com/soegaard/sci/blob/master/flomat/flomat.rkt#L73

Those aren’t the paths, they’re the ffi-lib
values. And the providing direction that Rajan would need is the other way, I think.

Ah!. You are right of course.

FWIW, I get this error on destination system ffi-lib: couldn't open "libblas.so.3" (libblas.so.3: cannot open shared object file: No such file or directory)
context...:
/usr/share/racket/collects/ffi/unsafe.rkt:131:0: get-ffi-lib
'#%embedded:flomat/flomat:: [running body]
temp35_0
for-loop
run-module-instance!
for-loop
[repeats 1 more time]
run-module-instance!
for-loop
[repeats 1 more time]
run-module-instance!
perform-require!
top-level: [running body]
eval-one-top
loop
[repeats 1 more time]

Right, there isn’t a solution that’s going to make flomat
work without putting libblas.so
somewhere found by dlopen
on the destination.

So you can either put it in the default search path, or set LD_LIBRARY_PATH
, or modify the rpath in the executable directly somehow.

I tried injecting rpath using patchelf
into the executable. That didn’t work. I’ll try injecting them into so files too and see how that goes

Thanks a lot for all your inputs btw :slightly_smiling_face:

There are some logging options to see what paths get tried by ffi-lib

Okay, in the case of raco distribute
and existing Racket code that doesn’t use define-runtime-path
, the best solution I know of is to just copy the shared libraries into right lib
subdirectory within the directory that raco distribute
creates, as a post-processing step.

It doesn’t look like executable in package is looking for libs in any of the sub directories of package. Which is weird

@rbt has joined the channel

hi that’s me!!! :slightly_smiling_face:

Write a function that takes as input a list of elements and returns a list with elements and their position after. For example, if the input to the function is (list ’a ’b ’c) then it will return (list a 1 b 2 c 3). Make sure to use recursion.

Can anyone help me in this

If I use map first it will on give me (a 1)

can you try writing a function that turns (list 'a 'b 'c)
into (list 'a 1 'b 'c)
? (that is, add one element’s position)

(Map(lambda (i) (String-append i “1”)) (List “a” “b” “c”))

not quite — it needs to be the element’s position as a number, not a string

so, you probably know this solution is wrong: (define (shreyas-homework input)
(map (lambda (i) (list i 1))
input))

That doesn’t sound right, and that’s not the behavior I see on a simple example. If this is example.rkt: #lang racket/base
(require ffi/unsafe)
(define lib (ffi-lib "nosuchlib"))
and I run raco make example.rkt
raco exe example.rkt
raco distribute example-dir example
PLTSTDERR="debug@ffi-lib" ./example-dir/bin/example
then the program logs an ffi-lib
failure, and the first two attempts it lists are files within ./example-dir/lib/plt/example/lib/
(but printed as absolute paths).

e.g. > (shreyas-homework (list 'a 'b 'c))
(('a 1) ('b 2) ('c 3))
which is nested

Thanks

Let me give it a try

so map
is one function that “transforms” lists — what other functions that operate on lists do you know?

you can see the refactoring tool in action here: https://github.com/9999years/racket-package-resyntax-action/pull/1#pullrequestreview-632676265

I guess fold

Like foldl and foldr

Maybe the (Racket) library isn’t using a relative path to refer to the foreign library. That might explain it.


Couldn’t the cblas-lib
definition be shortened to two case
clauses?

Yes - but that ruins indentation :wink:

what about cons
, car
, and cdr
?

Yeah First and rest

Got it

@andrei.demus has joined the channel

Hi, I saw the coverage tool for Racket and I’d like to know if such a thing exists for contracts, i.e. a tool that checks if functions are protected by a contract? I looked around, but didn’t find anything.

Thanks all. I will try all suggestions over/after the weekend. I am not done yet :slightly_smiling_face:

I’m trying to use current-test-case-around
to ensure each test in a test suite can implicitly time out, but it looks like I cannot do this inside of a test suite. An example is attached here: https://gist.github.com/wilbowma/79330280f474ecc456916787028206cc
My guess is that test-suites overwrite current-test-case-around
after processing the #:before
, making it impossible to use this parameter with test suites; is that right?

that’s correct AFAIK. When I modify these in Rackunit, your program works (after fixing minor mistakes in the program):
modified rackunit-lib/rackunit/private/test-case.rkt
@@ -45,7 +45,7 @@
(parameterize ([current-test-name name])
((current-test-case-around)
(λ ()
- (parameterize ([current-check-around plain-check-around])
+ (parameterize ([current-check-around (current-check-around)])
(test-thunk))))))
(define-simple-macro (test-begin body:expr ...)
modified rackunit-lib/rackunit/private/test-suite.rkt
@@ -95,7 +95,7 @@
(parameterize
([current-seed seed]
[current-test-case-around (test-suite-test-case-around fhere)]
- [current-check-around (test-suite-check-around fhere)])
+ [current-check-around (current-check-around)])
(let ([t test])
(run/inner t))
...

Thanks! Any way to make these actually usable to the end-user around test suites?

Here’s a crude attempt that makes some simplifying assumptions, but might be a good start: https://gist.github.com/camoy/51bcd96d654154609673a42670fa358f

I think there’s a pull request to fix this somewhere