File: linuxlib.pas

package info (click to toggle)
lazpaint 7.3-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 56,000 kB
  • sloc: pascal: 277,538; python: 2,494; makefile: 233; sh: 221
file content (135 lines) | stat: -rw-r--r-- 4,263 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
// SPDX-License-Identifier: LGPL-3.0-linking-exception

{ This unit allows to find the implementation of a library from its
  "linker name" whatever its version. }
unit linuxlib;

{$mode objfpc}{$H+}

{ Linker name
  -----------
  The linker name normally can only be used when compiling a program.
  It ends up with .so and does not have any version number. There isn't
  necessarily a file with this name though it may be provided in the
  development package (ending with -dev).
  - libwebp.so
  - libportaudio.so
  - libtiff.so
  - libpython.so


  Soname (qualified with a version number)
  ----------------------------------------
  The soname can be supplied to the LoadLibray function to load at runtime,
  without specifying any path. It is the same as the linker name, but with
  a version number. The file exists most of the time and it is generally
  a symbolic link to the implementation (or "real name").
  - libwebp.so.6
  - libportaudio.so.2
  - libtiff.so.5
  - libpython2.7.so


  Implementation or real name (with minor number)
  -----------------------------------------------
  The real name contains the implementation. It has a minor number and
  an optional release number. Most of the time, you don't need to know this
  name to use the library.
  - libwebp.so.6.0.2
  - libportaudio.so.2.0.0
  - libtiff.so.5.3.0
  - libpython2.7.so.1.0


  See: http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html }

interface

uses
  BGRAClasses, SysUtils;

{* Retrieves the full path of a library on Linux.

  Note that between different versions, there may be incompatibilities
  (in the signature of the functions or the record types).
  So make sure the functions you are calling are stable or
  check the version of the library once its loaded using one of its functions. }
function FindLinuxLibrary(ALinkerName: string; AMinimumVersion: integer = 0): string;

implementation

uses process;

function FindBinPath(AFilename: string): string;
const
  BinPaths: array[0..5] of string =
  ('/usr/local/sbin','/usr/local/bin','/usr/sbin','/usr/bin','/sbin','/bin');
var i: integer;
begin
  for i := 0 to high(BinPaths) do
    If FileExists(BinPaths[i] + '/' + AFilename) then
      exit(BinPaths[i] + '/' + AFilename);
  exit(AFilename);
end;

function FindLinuxLibrary(ALinkerName: string; AMinimumVersion: integer): string;
const
  OpenBracket = ' (';
  Arrow = ') => ';
var
  dataText, s, fileName, flags, path, versionStr: string;
  dataList, flagList: TStringList;
  openBracketPos, arrowPos, posDot: SizeInt;
  versionInt, errPos, i: integer;
  maxVersionInt: integer;
begin
  versionStr := copy(ExtractFileExt(ALinkerName), 2);
  val(versionStr, versionInt, errPos);
  if errPos = 0 then
  begin
    if AMinimumVersion = 0 then AMinimumVersion := versionInt;
    ALinkerName := ChangeFileExt(ALinkerName,'');
  end;
  result := '';
  maxVersionInt := AMinimumVersion-1;
  RunCommand(FindBinPath('ldconfig'), ['-p'], dataText, []);
  dataList := TStringList.Create;
  dataList.Text := dataText;
  flagList := TStringList.Create;
  for i := 0 to dataList.Count-1 do
  begin
    s := dataList[i];
    openBracketPos := pos(OpenBracket, s);
    arrowPos := pos(Arrow,s);
    if (openBracketPos <> 0) and (arrowPos <> 0) then
    begin
      fileName := trim(copy(s,1,openBracketPos-1));
      if fileName.StartsWith(ALinkerName+'.') then
      begin
        versionStr := copy(fileName, length(ALinkerName)+2, length(fileName)-length(ALinkerName)-1);
        posDot := pos('.', versionStr);
        if posDot > 0 then versionStr := copy(versionStr, posDot-1);
        val(versionStr, versionInt, errPos);
        if errPos = 0 then
        begin
          flags := copy(s, openBracketPos+length(OpenBracket), arrowPos-openBracketPos-length(OpenBracket));
          flagList.CommaText := flags;
          if {$IFNDEF CPU64}not{$ENDIF} (flagList.IndexOf('x86-64') <> -1) then
          begin
            path := copy(s, arrowPos+length(Arrow), length(s)-arrowPos-length(Arrow)+1);
            if versionInt > maxVersionInt then
            begin
              maxVersionInt := versionInt;
              result := path;
            end;
          end;
        end;
      end;
    end;
  end;
  flagList.Free;
  dataList.Free;
end;

end.