Afaik, dlopen(3), which I presume UFFI uses internally to load (shared)
libraries on demand (I cannot imagine anything else), looks in
LD_LIBRARY_PATH (DYLD_LIBRARY_PATH on macOS), not in PATH.
So let's focus on one of my question again, reworded here:
What is the strategy that UFFI internally uses in its own implementation
to search for a library? What if that library depends on other libraries
in turn? Where would these ones be searched for?
On 2018-10-17 12:05, Dimitris Chloupis wrote:
yeah I apologise for the wrong example , LibC utilises the
enviroment/system variables.
Generally speaking all OSes have a PATH variable that defines the places
where common libraries and tools are to be found. If you are on windows
you can type in the command prompt , "PATH", in Linux and MacOS is
"$PATH" . You can add your path in Windows using the system variables
dialog window, in MacOS and Linux it usually happens via .bash-config
file that setups the path but I am not so sure.
The easiest way is to do something like macModuleName does in the
LGitLibrary class the code is
macModuleName
| pluginDir |
pluginDir := Smalltalk vm binary parent / 'Plugins'.
#('libgit2.dylib' 'libgit2.0.dylib')
detect: [ :each | (pluginDir / each) exists ]
ifFound: [ :libName | ^ libName ].
self error: 'Module not found.'
Hope that helps
On Wed, Oct 17, 2018 at 12:54 PM Michel Onoff <michel.on...@web.de
<mailto:michel.on...@web.de>> wrote:
Hi Dimitris,
thanks for the long explanation.
As you can see from my example, I build the library with the
-undefined dynamic_lookup
flag to clang, so this should be compatible with your (3) option if I
understand you correctly. Compiling/linking this way should allow the
use of dlopen(3) from UFFI during the execution of Pharo code, exactly
as I try to simulate with my small test programs.
Pharo complains about not being able to load the module (the library),
even if it appears in the Pharo main folder. It does not report whether
it cannot find it or if it cannot bind it using dlopen(3).
Moreover, it is unclear to me how Pharo interacts with
DYLD_LIBRARY_PATH
(on macOS) or LD_LIBRARY_PATH (on Linux) environment variables if they
are set.
In other words, Where does it search for libraries?
Anyway, I'll try your script on cmake.
Regards
MO
for use with dlopen()
On 2018-10-17 11:32, Dimitris Chloupis wrote:
> I advice first of all the use of CMake , you can thank me later.
>
> CMake if you are not aware is the standard build system for C/C++
, it
> makes it super easy to build and compile projects so you dont
have to do
> what you are doing, call the compiler and pass the inifite amount of
> compiler flags that it needs.
>
> To understand how to build a library you have to understand first
what a
> library is.
>
> Libraries used by Pharo are known as either Shared Libraries on
Macos
> (dylib) and Linux (so) but Dynamically Linked Libraries on Windows
> (DLLs). They are executables designed to be called from another
> executable (this includes another library as well).
>
> Those libraries operate in 3 modes
> 1) Static linking
> 2) semi dynamic linking
> 3) dynamic linking
>
> (1) may come as suprise but yes those libraries can be linked to the
> executable and build inside the exrecutable. But in our case we done
> want that because it would mean to rebuild the VM.
> (2) is not what we want either because eventhough it builds the
library
> independently generating the usual exetension files I mentioned
above it
> includes its symbole table in the executable so you wont have to
do what
> UFFI does, wrap or map your code to those library functions. The
> equivelant for Pharo would mean that we would not need UFFI at
all but
> we do need to rebuld the VM to include ths symbol table. The symbole
> table basically includes the name of the functions, their signatures
> (type of arguments) and their corresponing adresses in memory
needed to
> access them.
>
> (3) is what UFFI does, in that cause the executable is not
affected at
> all so you dont need to to rebuild the vm. But you do need to
know where
> to find the library , to access its symbol table and make sure the
> variables your executable uses match the type and signature in the
> symbol table or else the executable wont able to locate and
correctly
> call these functions. Of course libraries can contain structs and
global
> variables as well but the concept is the same. Now this messy
part is
> handled by the UFFI although barely because it still needs from
you to
> provide the correct signature to the function.
>
> I am giving you the long version because you have to make sure
you build
> you library with (3) way and not (2). (1) can be easily avoid but
it is
> easy to mix (2) and (3). From there on its easy , locating the
library
> is provided as a string returned by a method , see how UFFI utilises
> LibC for example and from there on you just convert the
signatures to
> symbol arrays as described by the UFFI tutorials.
>
> For cmake you only need to use -> add_library(libraryname MODULE
${SRC}
> ). You can find a CmakeList.txt file that I use here
> https://gist.github.com/kilon/ff4b973bdeb3b0c0253ac373a4b2506a
>
> If you are wondering why its so big, its because the project I link
> against is huge and because I move the DLL to its build folder
instead
> of building it in the same folder as my source code. It CMake's
why of
> keeping things seperate and organised. Observe also that I use dll
> exension for Windows and MacOS, The extensions plays no role so I
> decided to go for the same extension to save time although
usually its
> preferable go for the standard extensions.
>
> Beware that if your library uses any external code even parts of
the C
> standard library those will have to be included , usually you
need only
> the header files, which is what SET INC is doing in my example,
while
> SET SRC includes only the library files. The inclusion of headers is
> super important because they are used to build the symbol table
which is
> the most important part of the library. Without a correctly build
symbol
> table the library is useless even when used from C/C++.
>
> On Wed, Oct 17, 2018 at 11:09 AM Michel Onoff
<michel.on...@web.de <mailto:michel.on...@web.de>
> <mailto:michel.on...@web.de <mailto:michel.on...@web.de>>> wrote:
>
> Hello,
>
> I've made some attempts to use the Pharo FFI. I've gone
through the
> documentation [1] and tried some examples.
>
> While the documentation is quite clear about using external
libraries
> from Pharo, it lacks details on how to build own libraries to
be used
> from Pharo.
>
> Specifically, I'm trying to build on all supported platforms,
namely
> macOS, Windows and Linux. Currently I've got Linux and
Windows under
> control, but I cannot find a systematic way to build on macOS.
>
> Here's an example for a library that I can use from a small test
> program
> but not from Pharo. Unfortunately, the diagnostic on Pharo is not
> detailed: it simply reports that it cannot load the module.
>
>
> clang -I <include-path> -O3 -c <source-path>
> ...
> clang -dynamiclib <object-files> -o lib<name>.dylib -undefined
> dynamic_lookup
>
> cp lib<name>.dylib <pharo-folder>
>
>
> Is there good documentation about how to correctly build
libraries so
> that they can be used from Pharo?
>
> Alternatively, are there details on how Pharo FFI searches for
> libraries
> and links them in the Pharo process?
>
>
> Regards
> MO
>
> ----
>
> [1] https://files.pharo.org/books-pdfs/booklet-uFFI/UFFIDRAFT.pdf
>
>