Skip to content

Fix & improve the MS-DOS build using MSVC compiler (3/4) - #823

Merged
gwsw merged 28 commits into
gwsw:masterfrom
ralish:dos-msvc-build
Sep 26, 2026
Merged

gwsw merged 28 commits into
gwsw:masterfrom
ralish:dos-msvc-build

Conversation

@ralish

@ralish ralish commented Sep 2, 2026 •

Copy link
Copy Markdown
Contributor

This PR fixes the MS-DOS build of less when building as a 16-bit executable using Microsoft Visual C++. In addition to the required fixes to enable a successful build, it also adds several improvements to the compilation and linking process for a smaller and faster binary. Finally, it 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 #822. A copy of the build output with these changes is attached along with the resulting statically linked binary if anyone wishes to test it themselves.

Attachments:

@ralish
ralish marked this pull request as ready for review September 2, 2026 03:23
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.
@gwsw
gwsw merged commit 344db94 into gwsw:master Sep 26, 2026
6 checks passed
@ralish
ralish deleted the dos-msvc-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