Skip to content

Fix & improve the OS/2 build using EMX runtime & GCC (4/4) - #824

Merged
gwsw merged 41 commits into
gwsw:masterfrom
ralish:os2-emx-build
Sep 26, 2026
Merged

gwsw merged 41 commits into
gwsw:masterfrom
ralish:os2-emx-build

Conversation

@ralish

@ralish ralish commented Sep 2, 2026 •

Copy link
Copy Markdown
Contributor

This PR fixes the OS/2 build of less using the EMX runtime with GCC (the only currently supported build environment). It also significantly improves the documentation on the build requirements and steps so others can more easily perform their own build.

Further details are available in each commit description. This PR is based on top of PR #823. A copy of the build output with these changes is attached along with a resulting statically linked binary if anyone wishes to test it themselves.

Attachments:

@ralish ralish changed the title Fix & improve the OS/2 build using the EMX runtime & GCC (4/4) Fix & improve the OS/2 build using EMX runtime & GCC (4/4) Sep 2, 2026
@ralish
ralish marked this pull request as ready for review September 2, 2026 03:23
@ralish
ralish force-pushed the os2-emx-build branch 2 times, most recently from 3a1b243 to 2dc81b8 Compare September 8, 2026 01:50
This is a superset of the previous ignored globs. The existing entries
are now categorised, and the following additional globs are ignored:

- lessmsg.inc
  Automatically generated by distfiles make target
- *.exe
  Executables on DOS, OS/2, and Windows systems
- *.obj
  Object files for some DOS, OS/2, and Windows compilers
- *.bak, *.log, *.tmp
  Backup, log, and temporary files
Shell scripts should always use LF line endings, even on platforms that
typically use a different end-of-line sequence (e.g. CRLF on Windows).
This commit ensures the files are checked-out with LF line endings even
on platforms for which the default end-of-line sequence is different.
For authors which have committed to the repository under multiple
identities, this instructs Git as to the canonical identity and ensures
commits are attributed to that identity. Also useful with `git shortlog`
when displaying a summary of Git authors and associated commit counts.
Appears to be a relic from when less supported pre-ANSI C and had to
choose between `void *` and `char *`.
Another apparent relic from when less supported pre-ANSI C and supported
K&R-compatible prototype macros.
Appears to be for planned but never implemented wide-character support.
It's never enabled anywhere, and if it were it only enables some (now
removed) upper/lower to/is macros. Even that's not true as those macros
are gated by `HAVE_WCTYPE` (no `_H` suffix) which isn't defined.
Renames the `less` target to `less.exe` so that incremental build works.
Previously every invocation would relink `less.exe` as a `less` file is
not output by the Makefile target.

Don't suppress error on copying defines.ds to defines.h as this is a
real problem that will break the build or give unexpected results.

Suppress error output on failing to delete files as this is harmless;
it's effectively always going to be because they don't exist.

Add missing ".obj" file extension to the Makefile suffix list.

Improves documentation and readability of the Makefile.
Auditing the codebase for usage of `ssize_t`` doesn't show any issues
with the narrowing of the datatype from 32/64-bits on newer systems.
less depends on non-ANSI library names so this option breaks the build.
Also remove the pre-processor definitions mapping non-ANSI library names
to their ANSI equivalents as MSVC takes care of this. Only a subset were
even valid; many are `stdlib` functions whose name hasn't changed.
All six compiler warnings are `C4761`:
`integral size mismatch in argument; conversion supplied`

The fix is to add explicit casts for arguments narrowed due to `int`
being a 16-bit data type.
Modern less has a lot more static data than historic versions. Under the
segmented memory model all near static data plus the stack must fit into
a single 64KB data segment (`DGROUP`). By default the compiler allocates
static data >= 256 bytes in a far data segment. Change this to be much
more aggressive, using >= 16 bytes as the size threshold, so we can fit
what's left in the `DGROUP` segment. This is safe under the large memory
model as all data pointers are far by default.
The `clreol()` function isn't defined in the MSVC DOS runtime. Use the
existing `clear_eol()` function which handles the runtime differences.
It won't ever be called as the call sites are all unreachable, but the
linker still requires a symbol.
The MSVC DOS runtime doesn't implement POSIX `sleep()` so we provide our
own implementation. Just perform a busy-wait given there's no scheduler
to yield to anyway.
The default of 2KB is woefully inadequate for modern less. With this
change we actually have a build and resulting binary that works.
The default is 8086, which continues to work but is positively ancient.
Targeting at least 80386 lets us reduce the binary size a bit and also
probably improves performance (likely imperceptible on modern CPUs). The
binary size reduction is ~12KB. For people who really need to run on
pre-386 processors the argument can be removed at the cost of a slightly
larger binary.
It's unnecessary for text-mode only functions, which is all less uses,
and saves another ~12KB from the binary.
Results in slightly faster code and a small binary size saving (~0.5KB).
Decompresses with a tiny stub loader at runtime. Performance impact is
effectively zero on all but the oldest systems, but space savings are
significant; around ~41KB currently, bringing the binary under 200KB.
I doubt they've been used (or tested) in at least a decade. They can
still be customised, but let's not provide a untested configuration.
They're only used on DOS builds so don't include them on other targets.
Might as well since it's available and consistent with what we do for
other targets where the runtime provides this function.
The compiler is expected to always be `cl` which makes the indirection
provided by the `CC` variable redundant. The includes can be resolved
through the `INCLUDE` environment variable and the libraries by the
`LIB` environment variable, both set by the `MSVCVARS.BAT` batch file.
Adds a clean target to remove compiler generated files.

Improves documentation and readability of the Makefile.
Some systems provide <locale.h> and setlocale() but not <langinfo.h>
(e.g. OS/2). The <langinfo.h> functionality is really only used when
HAVE_LOCALE_H and CODESET are defined, so scope the include to that.
I doubt they've been used (or tested) in at least a decade. They can
still be customised, but let's not provide a untested configuration.
Explicitly define the application type (WINDOWCOMPAT) and sets a file
description as a bonus. Without this the linker will emit warning L4071
stating the application type isn't specified and that WINDOWCOMPAT was
assumed. That's correct, but this gets rid of the annoying warning.
Both by explicitly declaring __open() through the EMX syscalls.h header
and correcting the call to use the expected three arguments. This only
ever worked by lucky coincidence; garbage off the stack was read for the
3rd argument but it was never used in the code path __open() takes.
Existing implementation treats `p` as a pointer into `gfilename`, which
is true for the `DECL_GLOB_NAME` branch, but the `DECL_GLOB_LIST` branch
treats `p` as a pointer to each globbed name in `_fnexplode()` (OS/2) or
`glob()` (DJGPP) storage. The `*--p = '\0'` writes one byte before the
start of the last matched filename, which corrupt's the glob library's
buffer. If the glob list is empty or every `shell_quote(p)` fails, then
`p` will be unitialized and corrupt a random memory location.
The warnings aren't actually valid as the variables will be initialised
before use in the actual code path taken, but initialising them is
harmless and ensures we get a clean build.
@gwsw
gwsw merged commit f0671ce into gwsw:master Sep 26, 2026
@ralish
ralish deleted the os2-emx-build branch September 27, 2026 00:07
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

Successfully merging this pull request may close these issues.

2 participants