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

Handle library api version in NativeCall #4751

Closed
p6rt opened this issue Nov 15, 2015 · 11 comments
Closed

Handle library api version in NativeCall #4751

p6rt opened this issue Nov 15, 2015 · 11 comments

Comments

@p6rt
Copy link

p6rt commented Nov 15, 2015

Migrated from rt.perl.org#126645 (status was 'resolved')

Searchable as RT126645$

@p6rt
Copy link
Author

p6rt commented Nov 15, 2015

From @Skarsnik

Some distribution (debian) does not provide the libfoo.so symlink in the binary that provide a libfoo. In the case of debian it's provided by libfoo-dev.

I was not able to find what was a standard behavior for the unversioned .so file

But allowing to specify the api version could fix this so NC can find libfoo.so.apiversion

Here a quick patch that make it work.
It allows to write

sub foo is native('libfoo​:42') ...

@p6rt
Copy link
Author

p6rt commented Nov 15, 2015

From @Skarsnik

diff --git a/lib/NativeCall.pm b/lib/NativeCall.pm
index cc5d1d0..0702e17 100644
--- a/lib/NativeCall.pm
+++ b/lib/NativeCall.pm
@​@​ -162,7 +162,10 @​@​ sub guess_library_name($lib) {
  else {
  $libname = $lib;
  }
-
+ my $apiversion = '';
+ if ($libname.index("​:")) {
+ ($libname, $apiversion) = $libname.split('​:');
+ }
  if !$libname.DEFINITE { '' }
  elsif $libname ~~ /\.<.alpha>+$/ { $libname }
  elsif $libname ~~ /\.so(\.<.digit>+)+$/ { $libname }
@​@​ -175,14 +178,16 @​@​ sub guess_library_name($lib) {
  $libname ~ '.' ~ $*VM.config<nativecall.so>
  }
  }
+ # seem like this one is called for rakudo
  elsif $*VM.config<dll> :exists {
  my $ext = $*VM.config<dll>;
  $ext ~~ s/^.*\%s//;
- "$libname$ext";
+ "$libname$ext" unless $apiversion;
+ "$libname$ext.$apiversion" if $apiversion and !$*DISTRO.is-win;
  }
  elsif $*DISTRO.is-win { "{$libname}.dll"; }
  # TODO​: more extension guessing
- else { "{$libname}.so"; }
+ else { "{$libname}.so"}
}

my %lib;

@p6rt
Copy link
Author

p6rt commented Nov 16, 2015

From @geekosaur

On Sat, Nov 14, 2015 at 7​:09 PM, Sylvain Colinet <
perl6-bugs-followup@​perl.org> wrote​:

Some distribution (debian) does not provide the libfoo.so symlink in the
binary that provide a libfoo. In the case of debian it's provided by
libfoo-dev.

I was not able to find what was a standard behavior for the unversioned
.so file

There isn't one, and really nobody should be linking to that because the
version may be any version a developer might want to work with, including
old ones to build something for backward compatibility. One should almost
always link to a specific API version.

Unfortunately, NativeCall doesn't really support this sensibly. For
example, on Windows if a DLL has an API version, it's usually appended to
the name part. (e.g. MSVCRT2.DLL)

I've been thinking about this a bit, and plan to write up a proposal when I
have something sensible to say.

--
brandon s allbery kf8nh sine nomine associates
allbery.b@​gmail.com ballbery@​sinenomine.net
unix, openafs, kerberos, infrastructure, xmonad http://sinenomine.net

@p6rt
Copy link
Author

p6rt commented Nov 16, 2015

The RT System itself - Status changed from 'new' to 'open'

@p6rt
Copy link
Author

p6rt commented Nov 16, 2015

From @Skarsnik

Le Dim 15 Nov 2015 20​:02​:52, allbery.b@​gmail.com a écrit :

On Sat, Nov 14, 2015 at 7​:09 PM, Sylvain Colinet <
perl6-bugs-followup@​perl.org> wrote​:

Some distribution (debian) does not provide the libfoo.so symlink in the
binary that provide a libfoo. In the case of debian it's provided by
libfoo-dev.

I was not able to find what was a standard behavior for the unversioned
.so file

There isn't one, and really nobody should be linking to that because the
version may be any version a developer might want to work with, including
old ones to build something for backward compatibility. One should almost
always link to a specific API version.

Unfortunately, NativeCall doesn't really support this sensibly. For
example, on Windows if a DLL has an API version, it's usually appended to
the name part. (e.g. MSVCRT2.DLL)

I've been thinking about this a bit, and plan to write up a proposal when I
have something sensible to say.

Did you have a look at my proposed fix? It's a quick fix and not probably the best solution. (it even support full version like 1.2.3!) But it's something x)

@p6rt
Copy link
Author

p6rt commented Nov 17, 2015

From @FROGGS

Hi, do you know if that patch also works on other linux distros, on BSDs and on osx?

@p6rt
Copy link
Author

p6rt commented Nov 17, 2015

From @Skarsnik

Le Lun 16 Nov 2015 23​:31​:15, FROGGS.de a écrit :

Hi, do you know if that patch also works on other linux distros, on
BSDs and on osx?

According to https://www.freebsd.org/doc/en/books/developers-handbook/policies-shlib.html and http://www.openbsd.org/faq/ports/specialtopics.html it should work too. I am not sure to understand exactly how freebsd handle minor version (it said it's ignored by ld or libtool, it's not clear)

For Os X it's similar​: https://developer.apple.com/library/mac/documentation/DeveloperTools/Conceptual/DynamicLibraries/100-Articles/DynamicLibraryDesignGuidelines.html#//apple_ref/doc/uid/TP40002013-SW20

but it's libname.version.dylib

@p6rt
Copy link
Author

p6rt commented Nov 19, 2015

From @Skarsnik

Le Mar 17 Nov 2015 04​:22​:05, scolinet@​gmail.com a écrit :

Le Lun 16 Nov 2015 23​:31​:15, FROGGS.de a écrit :

Hi, do you know if that patch also works on other linux distros, on
BSDs and on osx?

According to https://www.freebsd.org/doc/en/books/developers-
handbook/policies-shlib.html and
http://www.openbsd.org/faq/ports/specialtopics.html it should work
too. I am not sure to understand exactly how freebsd handle minor
version (it said it's ignored by ld or libtool, it's not clear)

For Os X it's similar​:
https://developer.apple.com/library/mac/documentation/DeveloperTools/Conceptual/DynamicLibraries/100-
Articles/DynamicLibraryDesignGuidelines.html#//apple_ref/doc/uid/TP40002013-
SW20

but it's libname.version.dylib

Ok I tried to create a new branch on rakudo for it (but I don't have the right)

So here another patch with tests. I don't have a win32 nor an Os X environement to test it on these plateform.

I added a warning if someone write 'libfoo' without an api version (but not in the case of what look like a path)

@p6rt
Copy link
Author

p6rt commented Nov 19, 2015

From @Skarsnik

0001-Add-a-support-for-apiversion-in-nativecall.patch
From a7beb3f9d2f9a6bacd8aa1741ed3076bf58a636d Mon Sep 17 00:00:00 2001
From: Skarsnik <scolinet@gmail.com>
Date: Thu, 19 Nov 2015 16:14:51 +0000
Subject: [PATCH] Add a support for apiversion in nativecall

---
 lib/NativeCall.pm             | 42 +++++++++++++++++++++---------------------
 t/04-nativecall/17-libnames.t | 16 ++++++++++++++++
 2 files changed, 37 insertions(+), 21 deletions(-)
 create mode 100644 t/04-nativecall/17-libnames.t

diff --git a/lib/NativeCall.pm b/lib/NativeCall.pm
index ea7bd50..b7146d1 100644
--- a/lib/NativeCall.pm
+++ b/lib/NativeCall.pm
@@ -155,7 +155,7 @@ my role NativeCallSymbol[Str $name] {
     method native_symbol()  { $name }
 }
 
-sub guess_library_name($lib) {
+sub guess_library_name($lib) is export(:libraries) {
     my $libname;
     if ($lib ~~ Callable) {
         $libname = $lib();
@@ -163,27 +163,27 @@ sub guess_library_name($lib) {
     else {
         $libname = $lib;
     }
-
-    if !$libname.DEFINITE { '' }
-    elsif $libname ~~ /\.<.alpha>+$/ { $libname }
-    elsif $libname ~~ /\.so(\.<.digit>+)+$/ { $libname }
-    elsif $*VM.config<load_ext> :exists { $libname ~ $*VM.config<load_ext> }
-    elsif $*VM.config<nativecall.so> :exists {
-        if $*KERNEL.name eq 'darwin' {
-            ($libname ~ '.' ~ $*VM.config<nativecall.so>).IO.absolute
-        }
-        else {
-            $libname ~ '.' ~ $*VM.config<nativecall.so>
-        }
-    }
-    elsif $*VM.config<dll> :exists {
-        my $ext = $*VM.config<dll>;
-        $ext ~~ s/^.*\%s//;
-        "$libname$ext";
+    #Already a full name
+    return $libname if ($libname ~~ /\.<.alpha>+$/ or $libname ~~ /\.so(\.<.digit>+)+$/);
+    
+    my $apiversion = '';
+    my $ext;
+    if $libname.index(':') {
+        ($libname, $apiversion) = $libname.split(':');
+    } else {
+        note "Consider adding the api version of the library you want to use, eg: $libname:1" if $libname ~~ /^<-[\.\/\\]>+$/;
     }
-    elsif $*DISTRO.is-win { "{$libname}.dll"; }
-    # TODO: more extension guessing
-    else { "{$libname}.so"; }
+    #Err, this is a mess, why so many way to get the extension?
+    $ext = "dynlib" if $*KERNEL.name eq 'darwin'; #Os X?
+    $ext = "dll" if $*DISTRO.is-win;
+    $ext = $*VM.config<load_ext>.substr(1) if $*VM.config<load_ext> :exists;
+    $ext = $*VM.config<nativecall.so>  if $*VM.config<nativecall.so> :exists;
+    {$ext = $*VM.config<dll>; $ext ~~ s/^.*\%s\.//;} if $*VM.config<dll> :exists;
+    $apiversion = '.' ~ $apiversion if $apiversion ne '';
+    return ("$libname$apiversion.$ext").IO.absolute if $*KERNEL.name eq 'darwin';
+    return "$libname.$ext$apiversion" if !$*DISTRO.is-win;
+    return "$libname.$ext" if $*DISTRO.is-win;
+    return "$libname.so";
 }
 
 my %lib;
diff --git a/t/04-nativecall/17-libnames.t b/t/04-nativecall/17-libnames.t
new file mode 100644
index 0000000..cac72cb
--- /dev/null
+++ b/t/04-nativecall/17-libnames.t
@@ -0,0 +1,16 @@
+use Test;
+
+use NativeCall :libraries;
+
+plan 6;
+
+if $*KERNEL ~~ 'linux' {
+	ok guess_library_name("libfoo") eq "libfoo.so", "libfoo is libfoo.so and should warn";
+	ok guess_library_name("libfoo:3") eq "libfoo.so.3", "libfoo:3 is libfoo.so.3";
+	ok guess_library_name("libfoo.so") eq "libfoo.so", "libfoo.so is libfoo.so";
+	ok guess_library_name("./libfoo") eq "./libfoo.so", "./libfoo is ./libfoo.so";
+	ok guess_library_name("./libfoo.so") eq "./libfoo.so", "./libfoo.so is ./libfoo.so";
+	ok guess_library_name("/libfoo.so") eq "/libfoo.so", "/libfoo.so is /libfoo.so";
+} else {
+	skip 6;
+}
-- 
2.6.2

@p6rt
Copy link
Author

p6rt commented Dec 22, 2015

From @FROGGS

Patches by Skarsnik++​:
  rakudo/rakudo@6ed069f
  rakudo/rakudo@5e0c0ca

Tests​:
  rakudo/rakudo@522e03c

Closing as resolved. Thanks Skarsnik++!

@p6rt p6rt closed this as completed Dec 22, 2015
@p6rt
Copy link
Author

p6rt commented Dec 22, 2015

@FROGGS - Status changed from 'open' to 'resolved'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant