Re: Trying to link in modules
Thanks! On Sun, Jun 20, 2021 at 6:42 AM wrote: > > I've got a module mymod in mymod.scm: > > > >[...] > > > > However, I can't figure out how to do the same thing with mymod as > > non-shared objects. I tried > > > > csc -c -J mymod.scm > > csc -c mymod.import.scm > > csc -static -o trymod.static mymod.o mymod.import.o trymod.scm > > > > but I got > > > > Undefined symbols for architecture x86_64: > > > > "_C_mymod_toplevel", referenced from: > > _f_138 in trymod.o > > ld: symbol(s) not found for architecture x86_64 > > clang: error: linker command failed with exit code 1 (use -v to see > > invocation) > > Error: shell command terminated with non-zero exit status 256: 'clang' > > 'mymod.import.o' 'mymod.o' 'trymod.o' -o 'trymod.static' -m64 > > -L/usr/local/Cellar/chicken/5.2.0/lib > > /usr/local/Cellar/chicken/5.2.0/lib/libchicken.a -lm > > When loading a shared object, the CHICKEN runtime uses the libld API > to obtain the entry point ("C_toplevel") to invoke top-level > initialization code > of the module (which also sets up global bindings, etc.). But in a > statically > linked executable, all entry points of linked modules must be available > under > a separate name, so that they can be distinguished from each other. > > What we do is to give the module (the binary *.o module) a name, which is > called "unit", so mymod would have, for example, the unit name "mymod", > which produces the entry point "C_mymod_toplevel". So you can link any > number of separately compiled binary objects (containing modules) and > their names don't clash. > > So, to make it work: > > csc -c -J mymod.scm -unit mymod > # compiling the import library is not needed > csc -static -o trymod.static -uses mymod mymod.o trymod.scm > > The main file (trymod) doesn't need to resolve the imports, so you can omit > linking the import library. "-unit" gives the module a unit name, "-uses" > tells > the main module to invoke the toplevel of the linked module. > > This mechanism is a source of great confusion, but this mainly comes from > the fact that static linking uses a facility for resolving module toplevel > and > initialization code from the whole module and namespacing machinery. > > --- > BTW, the "csm" utility, provided by the egg of the same name, figures this > out > automatically, just put trymod.scm and mymod.scm into an empty directory > and enter > > csm -program trymod > > or > > csm -program trymod -static > > Add -d and -v to see what the program is doing and how things are compiled. > > > felix > > -- T. Kurt Bond, tkurtb...@gmail.com, https://tkurtbond.github.io
Re: Trying to link in modules
> I've got a module mymod in mymod.scm: > >[...] > > However, I can't figure out how to do the same thing with mymod as > non-shared objects. I tried > > csc -c -J mymod.scm > csc -c mymod.import.scm > csc -static -o trymod.static mymod.o mymod.import.o trymod.scm > > but I got > > Undefined symbols for architecture x86_64: > > "_C_mymod_toplevel", referenced from: > _f_138 in trymod.o > ld: symbol(s) not found for architecture x86_64 > clang: error: linker command failed with exit code 1 (use -v to see > invocation) > Error: shell command terminated with non-zero exit status 256: 'clang' > 'mymod.import.o' 'mymod.o' 'trymod.o' -o 'trymod.static' -m64 > -L/usr/local/Cellar/chicken/5.2.0/lib > /usr/local/Cellar/chicken/5.2.0/lib/libchicken.a -lm When loading a shared object, the CHICKEN runtime uses the libld API to obtain the entry point ("C_toplevel") to invoke top-level initialization code of the module (which also sets up global bindings, etc.). But in a statically linked executable, all entry points of linked modules must be available under a separate name, so that they can be distinguished from each other. What we do is to give the module (the binary *.o module) a name, which is called "unit", so mymod would have, for example, the unit name "mymod", which produces the entry point "C_mymod_toplevel". So you can link any number of separately compiled binary objects (containing modules) and their names don't clash. So, to make it work: csc -c -J mymod.scm -unit mymod # compiling the import library is not needed csc -static -o trymod.static -uses mymod mymod.o trymod.scm The main file (trymod) doesn't need to resolve the imports, so you can omit linking the import library. "-unit" gives the module a unit name, "-uses" tells the main module to invoke the toplevel of the linked module. This mechanism is a source of great confusion, but this mainly comes from the fact that static linking uses a facility for resolving module toplevel and initialization code from the whole module and namespacing machinery. --- BTW, the "csm" utility, provided by the egg of the same name, figures this out automatically, just put trymod.scm and mymod.scm into an empty directory and enter csm -program trymod or csm -program trymod -static Add -d and -v to see what the program is doing and how things are compiled. felix
Re: Trying to link in modules
Hi Kurt, I think the problem is missing flags and parameters when fuilding a static extension. I'm afraid I don't know exactly what they are, but hopefully I can give some pointers to how you can find them. chicken-install will extensions first as a shared object, and then as a static one by default. ~/p/t/chicken-mtest > cat mymod.egg ((components (extension mymod))) ~/p/t/chicken-mtest > chicken-install -v /data/data/com.termux/files/home/prj/tmp/chicken-mtest/mymod.link -host -D compiling-extension -c -unit mymod -D compiling-static-extension -C -I/data/data/com.termux/files/home/prj/tmp/chicken-mtest -O2 -d1 mymod.scm -o /data/data/com.termux/files/home/prj/tmp/chicken-mtest/mymod.static.o That gives a lot of output, but notice it installs a mymod.o file that trymod can use when compiled statically. Let's see how trymod behaves as normally: ~/p/t/chicken-mtest > csc trymod.scm ~/p/t/chicken-mtest > strace ./trymod ^&1 |grep mymod newfstatat(AT_FDCWD, "/data/data/com.termux/files/usr/lib/chicken/11/mymod.so", {st_mode=S_IFREG|0755, st_size=13232, ...}, 0) = 0 newfstatat(AT_FDCWD, "/data/data/com.termux/files/usr/lib/chicken/11/mymod.so", {st_mode=S_IFREG|0755, st_size=13232, ...}, 0) = 0 openat(AT_FDCWD, "/data/data/com.termux/files/usr/lib/chicken/11/mymod.so", O_RDONLY|O_CLOEXEC) = 3 openat(AT_FDCWD, "/data/data/com.termux/files/usr/lib/chicken/11/mymod.so", O_RDONLY|O_CLOEXEC) = 3 write(1, "Hello, World, I'm in mymod!\n", 28Hello, World, I'm in mymod! And now with static compilation: ~/p/t/chicken-mtest > csc -static trymod.scm ~/p/t/chicken-mtest > strace ./trymod ^&1 |grep mymod write(1, "Hello, World, I'm in mymod!\n", 28Hello, World, I'm in mymod! I hope that is what you're after. Note this uses the installed version of mymod (chicken-status), not the one in PWD. You can inspect the *.build.sh files that chicken-install produces for inspiration, or tweak the .egg-file to suit your needs. Cheers, Kris On Sun, Jun 20, 2021, 09:57 T. Kurt Bond wrote: > I've got a module mymod in mymod.scm: > > (module mymod (hello) > (import scheme) > (define (hello) > (display "Hello, World, I'm in mymod!") > (newline))) > > and I've got a module trymod in trymod.scm: > > (module trymod () > (import scheme) > (import mymod) > (hello) > ) > > and when I compile them like this: > > csc -s -J mymod.scm > csc -s mymod.import.scm > csc trymod.scm > > it produces an executable trymod that runs and dynamically loads mymod.so, > unloads it, and loads it again, then produces the expected output, calling > the function hello in mymod as running it on macOS with > DYLD_PRINT_LIBRARIES=YES > ./trymod shows. > > ... > dyld: loaded: <59A8239F-C28A-3B59-B8FA-11340DC85EDC> > /usr/lib/libc++.1.dylib > dyld: loaded: ./mymod.so > dyld: unloaded: ./mymod.so > dyld: loaded: ./mymod.so > Hello, World, I'm in mymod! > > However, I can't figure out how to do the same thing with mymod as > non-shared objects. I tried > > csc -c -J mymod.scm > csc -c mymod.import.scm > csc -static -o trymod.static mymod.o mymod.import.o trymod.scm > > but I got > > Undefined symbols for architecture x86_64: > > "_C_mymod_toplevel", referenced from: > _f_138 in trymod.o > ld: symbol(s) not found for architecture x86_64 > clang: error: linker command failed with exit code 1 (use -v to see > invocation) > Error: shell command terminated with non-zero exit status 256: 'clang' > 'mymod.import.o' 'mymod.o' 'trymod.o' -o 'trymod.static' -m64 > -L/usr/local/Cellar/chicken/5.2.0/lib > /usr/local/Cellar/chicken/5.2.0/lib/libchicken.a -lm > > > What am I doing wrong? > -- > T. Kurt Bond, tkurtb...@gmail.com, https://tkurtbond.github.io >
Trying to link in modules
I've got a module mymod in mymod.scm: (module mymod (hello) (import scheme) (define (hello) (display "Hello, World, I'm in mymod!") (newline))) and I've got a module trymod in trymod.scm: (module trymod () (import scheme) (import mymod) (hello) ) and when I compile them like this: csc -s -J mymod.scm csc -s mymod.import.scm csc trymod.scm it produces an executable trymod that runs and dynamically loads mymod.so, unloads it, and loads it again, then produces the expected output, calling the function hello in mymod as running it on macOS with DYLD_PRINT_LIBRARIES=YES ./trymod shows. ... dyld: loaded: <59A8239F-C28A-3B59-B8FA-11340DC85EDC> /usr/lib/libc++.1.dylib dyld: loaded: ./mymod.so dyld: unloaded: ./mymod.so dyld: loaded: ./mymod.so Hello, World, I'm in mymod! However, I can't figure out how to do the same thing with mymod as non-shared objects. I tried csc -c -J mymod.scm csc -c mymod.import.scm csc -static -o trymod.static mymod.o mymod.import.o trymod.scm but I got Undefined symbols for architecture x86_64: "_C_mymod_toplevel", referenced from: _f_138 in trymod.o ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation) Error: shell command terminated with non-zero exit status 256: 'clang' 'mymod.import.o' 'mymod.o' 'trymod.o' -o 'trymod.static' -m64 -L/usr/local/Cellar/chicken/5.2.0/lib /usr/local/Cellar/chicken/5.2.0/lib/libchicken.a -lm What am I doing wrong? -- T. Kurt Bond, tkurtb...@gmail.com, https://tkurtbond.github.io