-
Notifications
You must be signed in to change notification settings - Fork 31
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
Build dynamic libraries #357
Conversation
Some testing on my primary Linux system shows that the build dir somehow gets included in # Note 1: The full path to the build directory's bin folder must be included in $PATH
# Note 2: The Linux system I test on symlinks /bin to /usr/bin (usrmerge)
$ PATH=/usr/bin:/home/johno/GitRepos/KornShell/ksh/arch/linux.i386-64/bin ksh -c 'whence -a chmod; /home/johno/GitRepos/KornShell/ksh/arch/linux.i386-64/bin/chmod --version'
chmod is a tracked alias for /usr/bin/chmod
chmod is a shell builtin version of /home/johno/GitRepos/KornShell/ksh/arch/linux.i386-64/bin/chmod
version chmod (AT&T Research) 2012-04-20
# Note that there is no chmod command in the build dir bin folder
$ [ -e /home/johno/GitRepos/KornShell/ksh/arch/linux.i386-64/bin/chmod ]; echo $?
1 The ksh/src/cmd/ksh93/bltins/whence.c Lines 290 to 292 in 430e478
Line 145 in 430e478
|
The cause of the regression test failure on my machine is this # use { no NO } prefix to permanently disable #
PLUGIN_LIB=cmd
FPATH=../fun The specific setting that causes shell builtins to become loadable from $ mkdir /tmp/bin
$ PATH=/usr/bin:/tmp/bin ksh -c 'whence -a chmod; /tmp/bin/chmod --version'
chmod is a tracked alias for /usr/bin/chmod
ksh: /tmp/bin/chmod: not found
$ echo 'PLUGIN_LIB=cmd' > /tmp/bin/.paths
$ PATH=/usr/bin:/tmp/bin ksh -c 'whence -a chmod; /tmp/bin/chmod --version'
chmod is a tracked alias for /usr/bin/chmod
chmod is a shell builtin version of /tmp/bin/chmod Relevant code: Lines 1613 to 1618 in 430e478
Line 52 in 430e478
Lines 850 to 860 in 430e478
Lines 1547 to 1554 in 430e478
|
Nice find. If I move that On macOS, after disabling System Integrity Protection so I can use
|
I've been tracing the execution of this code with debug output commands. On Linux, it looks like the Lines 850 to 860 in 430e478
dlllook() returns NULL.
On Linux, this causes Lines 871 to 872 in 430e478
sh.bltins_tree so it goes back to found: .
So it looks like we need to investigate why |
Actually, is that incorrect? It seems consistent with what sh.1 describes for the |
Yes, the Linux behaviour is correct, even though that's what breaks the regression tests. On Slackware:
The above is consistent with the
…it doesn't seem to work at all. I think that's a bug for another day. For now, I'm content to just get rid of that |
It should be noted that
That's not to say the current behavior doesn't have any issues. The
Additionally, the libcmd builtins don't become accessible unless $ PATH=/usr/bin:/tmp/bin arch/*/dyn/ksh -c '/tmp/bin/tail'
arch/linux.i386-64/dyn/ksh: /tmp/bin/tail: not found |
So, I pushed a commit to my And look what that exposed: on Linux (CI runner):
…and on macOS:
All other tests pass though, on both Linux and macOS.
|
What I had missed is that The content of that one, on my system, is:
After removing that So, that is also to note for a future bugfix. For now, I'll get rid of the creation of that from the Mamfile as well. |
This is minor, but I have a patch that fixes some typos I saw in the pull request: typo-fixes.patch--- a/bin/dynamic
+++ b/bin/dynamic
@@ -104,7 +104,7 @@ install)
shift 2
# commands to install by default
test "$#" -eq 0 && set -- ksh shcomp # pty suid_exec
- # check if we need to build, determining soure command paths;
+ # check if we need to build, determining source command paths;
# install from dyn/ or, if not found, from bin/
for f do
shift
--- a/src/cmd/ksh93/Mamfile
+++ b/src/cmd/ksh93/Mamfile
@@ -1390,7 +1390,7 @@ make install
make libshell.dyn
prev libshell.a archive
note *
- note * Link a dynamic libary if appropriate variables were exported.
+ note * Link a dynamic library if appropriate variables were exported.
note * See bin/dynamic in the source directory for more information.
note *
exec - set -e
--- a/src/lib/libast/Mamfile
+++ b/src/lib/libast/Mamfile
@@ -6103,7 +6103,7 @@ make install
make libast.dyn
prev libast.a archive
note *
- note * Link a dynamic libary if appropriate variables were exported.
+ note * Link a dynamic library if appropriate variables were exported.
note * See bin/dynamic in the source directory for more information.
note *
exec - set -e
--- a/src/lib/libcmd/Mamfile
+++ b/src/lib/libcmd/Mamfile
@@ -761,7 +761,7 @@ make install
make libcmd.dyn
prev libcmd.a archive
note *
- note * Link a dynamic libary if appropriate variables were exported.
+ note * Link a dynamic library if appropriate variables were exported.
note * See bin/dynamic in the source directory for more information.
note *
exec - set -e
--- a/src/lib/libdll/Mamfile
+++ b/src/lib/libdll/Mamfile
@@ -270,7 +270,7 @@ make install
make libdll.dyn
prev libdll.a archive
note *
- note * Link a dynamic libary if appropriate variables were exported.
+ note * Link a dynamic library if appropriate variables were exported.
note * See bin/dynamic in the source directory for more information.
note *
exec - set -e |
Actually, I reproduced the issue, with a libshell that definitely has vmalloc disabled. I'll have to disable the compilation of that completely. |
This makes sense, since the
|
I recently found a patch which adds support for |
Thanks. It doesn't hurt, so I'll add it for completeness' sake, but it's of limited use since |
That's not true. When SIP is enabled, |
I've found a bug in
This occurs because the ksh/src/cmd/ksh93/tests/shtests Lines 275 to 277 in 5d8ae36
This can be fixed by just detecting if the folder exists: folder-detect.patch--- a/src/cmd/ksh93/tests/shtests
+++ b/src/cmd/ksh93/tests/shtests
@@ -272,7 +272,7 @@ if [[ -d /usr/ucb ]]
then PATH=$PATH:/usr/ucb
fi
PATH=$PATH:$d
-if [[ $INSTALLROOT && -r $INSTALLROOT/bin/.paths ]]
+if [[ $INSTALLROOT && -d $INSTALLROOT/bin ]]
then PATH=$INSTALLROOT/bin:$PATH
fi
if [[ ${SHELL%/*} != $INSTALLROOT/bin ]] |
In my testing, this is now working fine on macOS, Linux (Slackware, Debian, Void with musl, NixOS), *BSD (DragonFly, Free, Net, Open), and Solaris (10.1 and 11.4), which covers most of the *nix market. I'd like to offer this functionality in the next beta and I think it's either ready or close to ready. Cygwin can wait. Please test what we've got now. |
I could not figure out from all the commentary above on how to compile a dynamic version of ksh let alone how to go about running shtests against it. I tried a few things but all failed. By running
Can someone please list out the build and test steps so that I may assist? |
Sorry about that @hyenias. Yes,
This is normal. The libraries are not yet installed in the library search path, so the system can't find them. You can do one of the following:
Hope this helps. |
Thanks! As I am testing, I do not want to install anything anywhere just keep all the files right where they are. Unfortunately, when I attempted a simple version display the dynamic ksh immediately had a segmentation fault before I even attempted to run shtests:
|
Here is the backtrace using gdb after I deleted my arch folder and compiled again using
|
11741ff
to
2084e97
Compare
I built @9d9327 on macOS 11.6.1 and it appears to work. I think I'm missing how to run Edit: Don't mind me, stupid me hasn't used |
The current PR cannot produce a functional dynamically linked executable under ASan because the ASan stacktrace
|
src/cmd/INIT/Mamfile: - Move .paths from bin into dyn/bin. - Drastically simplify -- just cat the contents that the old code generated. I have no idea why that was so complicated. bin/package: - Remove redunant .paths generation code. src/cmd/INIT/dylink.sh: - Disable dynamic libraries if AST_NO_DYLIB is exported. - Disable dynamic libraries on untested systems unless AST_DYLIB_TEST is exported. - Tweaks.
Putting the .paths file in dyn/bin somehow makes the linker fail, with lots of undefined symbols, when the shell used to compile is /bin/ksh on Debian 11 (ksh 93u+ 2012-08-01). I think I am going to nix the whole .paths thing from the shell -- in my view it's just a bad idea.
@JohnoKing writes: > The current PR cannot produce a functional dynamically linked > executable under ASan because the regcomp function gets overriden > by ASan, despite linking with --no-as-needed. Applying the > regcomp patch fixes this crash and allows the regression tests to > complete with no more failures than a statically linked binary > compiled from the dev branch.
Alright then, this is now confirmed good on Linux, Android, macOS, FreeBSD, NetBSD, OpenBSD, and illumos (plus presumably Solaris). After nearly 2.5 years, it's time to commit this at long last, so we can subject it to wider testing. Some systems are still untested but they can be tested (and then whitelisted in dylink.sh) later. Many thanks for all the help, everyone. |
Actually, I forgot about one thing: I'd like the file version number to be individually settable for each dynamic library. This is easy enough to do from the Mamfiles, so won't take long. |
They can now be set by changing DYLIB_VERSION in each of the four libraries in their respective Mamfiles.
This commit re-adds support for building a dynamically linked ksh with libast, libdll, libcmd, and libshell available as dynamic libraries for other applications to use. Previously, this required nmake; as of this commit, we use a helper script dylink.sh instead, which does all the necessary platform-specific things and can be easily extended to add support for new platforms. Currently tested and supported platforms are Linux, Android, macOS, FreeBSD, NetBSD, OpenBSD, and illumos/Solaris. Summary of important changes: src/cmd/ksh93/SHOPT.sh: - Enable SHOPT_DYNAMIC by default. This enables the '-f' option to the 'builtin' command, making it possible to load builtins from dynamic/shared libraries. This mostly makes sense for a dynamically linked ksh, as that is needed to allow ksh and builtins to share the same libraries such as libast. src/cmd/INIT/dylink.sh: - Added. This is a dynamic linking tool to invoke from Mamfiles. - Disable dynamic libraries if AST_NO_DYLIB is exported. - Disable dynamic libraries on untested systems unless AST_DYLIB_TEST is exported. bin/package: - Add support for $INSTALLROOT/dyn subdirectory. - Set LD_LIBRARY_PATH, etc. to point to dyn/lib. - Prefix dyn/bin to $PATH. - do_install(): - Prefer dynamically linked versions for installing, if they have been built. - If dyn/lib exists, install not only the dynamic libraries but also the dev stuff: AST headers and section 3 manual pages. - Remove generation of .paths file. It causes regression test failures because of how built-ins are bound to different paths when found via a .paths file. This functionality is deprecated and may be removed from ksh 93u+m/1.1 and up. bin/shtests: - Relaunch self via 'bin/package use' to pull in the necessary environment stuff to make the pre-installed dynamically linked binaries work. src/cmd/INIT/make.probe: - Add probe for the --as-needed and --no-as-needed linker options. To make dynamic libraries work on Linux arm64, we need to pass --no-as-needed to the linker on Linux to avoid glibc interfering with libast in identically named functions like AST regcomp(3). Linux systems vary as to whether --as-needed is on by default. Thanks to Lukáš Zaoral at Red Hat for finding the key to the fix. src/cmd/INIT/mamprobe.sh: - Update version number. This change causes mamake to redo the probe (it checks for a change in mamprobe but not in make.probe; I should probably fix that at some point). We need mamake to redo the probe for the --no-as-needed addition to take effect. **/Mamfile: - Use the --no-as-needed probe result (either -Wl,-no-as-needed or empty) from ${mam_cc_LD_NOASNEEDED} whenever linking anything; add it to LDFLAGS before invoking dylink. - ksh and shcomp also need the results of the existing --export-dynamic probe; this option is needed on Linux as without it ksh fails to export symbols to loadable builtins. See: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=821806 Thanks to Johnothan King. src/lib/libast/features/map.c, src/lib/libast/regex/regexec.c, src/lib/libast/regex/regnexec.c, src/lib/libast/regex/regrexec.c, src/lib/libast/regex/regsubexec.c: - Map regcomp and all the other AST regex functions via macros so they get an _ast_ prefix. This allows a functional dynamically linked executable to exist under ASan because the regcomp function gets overriden by ASan, despite linking with --no-as-needed. Thanks to Johnothan King. src/lib/libast/comp/errno.c: - Make one trivial change (copyright year) to force libast to relink -- which then triggers a relink of everything else. Co-authored-by: Johnothan King <johnothanking@protonmail.com> Co-authored-by: Lukáš Zaoral <lzaoral@redhat.com>
This is an attempt to amend the build system to support dynamic libraries. It is mostly working on Linux, macOS, *BSD and Solaris.
My first attempt dropped dynamic libraries in
arch/*/lib
. But that confusedbin/packace
so hopelessly it didn't even run.So instead this commit separates the new functionality cleanly from the existing AT&T mess. It uses a wrapper script,
bin/dynamic
, that exports some environment variables. New script code is added to relevantMamfile
s that use these variables to build dynamic libraries. It checks if$DYLIB_CCFLAG
is set and if not, it does nothing. So nothing changes if this wrapper script is not used.It also adds an installation feature,
bin/dynamic install
, that either creates a nice directory tree complete with manual pages and include headers, or it will install into an existing directory tree without overwriting it. By default,ksh
andshcomp
are installed, but that selection can be overridden by providing command name arguments after the root directory, for example:Of course, this is not ready. Problems persist.
Most importantly, major regressions appear on various systems when
ksh
is linked dynamically.On Linux,$PATH
search is broken on shell initialisation, causing various regression test failures and a basically unusable shell binary. This a problem I've seen before on some ancient systems, I just chalked it up to them being obsolete, but no, it's a real ksh bug and it needs fixing before any of this is ready for prime time. Help! :-)There are different regression test failures on the BSDs and on macOS.It fails a lot on OpenBSD.Secondly, I have not succeeded at using standard library versioning on systems other than macOS. macOS uses the version number before the
.dylib
extension, making it possible to link to specific versions using something like-last.1.0
without trickery. On Linux and other systems the version number follows the extension, making that impossible, and I don't know a way around it. Simply using the path to the library is not an option as that makes the binary dependent on your development directory. So this uses a naming scheme that is similar to macOS on all systems, with an additional 93u+m tag to make it clear this is our version and not AT&T's. This also works on systems that use a.so
extension, but is idiosyncratic on those. I don't know if this actually a problem.Perhaps we need to use something like GNU
libtool
instead for generating dynamic libraries. That should be quite doable as theMamfile
s can execute any shell script, but I don't understand the legalities of combining GPL'ed software with ours. Plus I'd like to avoid adding bloat if at all possible.bin/dynamic
:src/*/*/Mamfile
:exec -
scripts to handle dynamic building.src/cmd/ksh93/Mamfile
:setv mam_cc_FLAGS
tosetv mam_cc_FLAGS ${mam_cc_DLL}
is important; this makeslibshell
compile with-fPIC
or whatever flagmamprobe
detects to make the compiler generate relocatable code that is usable in dynamic libraries. Thatmam_cc_DLL
variable is what's exported bymamprobe
.Resolves: #302