README.md 39.7 KB
Newer Older
S
Shengliang Guan 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820
MsvcLibX - A set of MSVC Library eXtensions
===========================================


Introduction
------------

The MsvcLibX library is built upon 30 years of work.  
It exists because the Microsoft Visual C/C++ library is only a subset of the
standard C library, and I wanted to port to DOS and Windows programs using some
of the missing parts.  
Initially Microsoft C compilers for MS-DOS tried to be as compliant as possible
with the standard C library. Then Microsoft rewrote their library for Windows.
But when the WIN32 API became prevalent, Microsoft apparently lost interest,
and stopped porting to MS-DOS and Windows the new C include files and library
routines that got standardized over the years.  
To the point that's it's now impossible to rebuild any recent Posix/Unix/Linux
program using the MSVC library.  

MsvcLibX adds a number of standard include files and library routines that I've
needed over the years. For example the directory access routines defined in
dirent.h, or the symbolic link support in unistd.h.  
It also includes a number of useful routines and macros, either needed 
internally to implement and debug the above, or made necessary by irresolvable 
incompatibilities between Unix and Windows.  

Other major features of the MsvcLibX library are:

* A powerful make system, based on Microsoft nmake files, that allow building
  multiple versions of the same program (Ex: DOS/WIN32/WIN64) with one simple
  command. And in most cases without having to write any dedicated make file.
* Support for UTF-8 sources, allowing to build programs working in any code page.
* Support for NTFS symlinks and junctions.
* Support for DOS, and Windows 95 targets, for targeting old computers.
* Support for bound DOS+Windows programs, for truly universal executables that
  work in *all* versions of DOS and Windows.

An obvious alternative exists for building Windows programs: MinGW.
But I started all this before MinGW even existed. And, surprisingly, even MinGW
still has holes in 2014, where MsvcLibX in significantly more advanced.  
Another alternative is CygWin. This one is more complete, but also much more 
heavyweight. Using programs built with CygWin requires installing CygWin DLLs.
Copying the program .exe from one system to the next is not sufficient. In that
sense, MinGW or MsvcLibX are much better.  

Contrary to MinGW and CygWin, MsvcLibX does not attempt to be complete, and is
unlikely to ever be. But any contribution of improvements is welcome.  
Likewise, any help at contributing unique MsvcLibX features to MinGW is welcome. 

Jean-François Larvoire
2016-09-29


Building the MsvcLibX library
-----------------------------

On a recent Windows PC, with Microsoft Visual C++ compilers installed:

- Select a base work directory. I'll call it %BASEDIR% in the examples below:

        set "HOME=%HOMEDRIVE%%HOMEPATH%"
        set "BASEDIR=%HOME%\Documents\SRC"
        md "%BASEDIR%"
        cd "%BASEDIR%"
  
- Extract the MsvcLibX archive into a work subdirectory. Ex: %BASEDIR%\MsvcLibX\   
  This will put files in several subdirectories: include, src

- Open a cmd window, and run:

        cd "%BASEDIR%\MsvcLibX\src" 
        configure
        make

The configure.bat script will locate your MSVC tools, and generate a config
file. It needs to be run once initially, then again if new MSVC tool versions
are installed.  
The make.bat script should take care of everything, and rebuild normal and debug
versions of the MsvcLibX.lib library for all operating systems your tools support.
In the end, it defines system environment variable MSVCLIBX, necessary for
building programs using the MsvcLibX.lib library.  

Requirements:

- Microsoft Visual C++ compiler and linker for Windows 32 and 64 bits targets.
- Microsoft Windows SDK. (May be installed along with Visual C++)

As of 2015-12-10, I've tested the make.bat script and make files with Visual C++
2005, 2008, 2012, and 2015, and Windows SDK 5.2, 8.1, and 10.  
Support for older versions is still built-in, but I've not tested it for long.  
Support for newer versions will require minor tweaks in configure.bat.
Note that configure.bat does not depend on MSVC's vcvars.bat. It will attempt
to locate and use the latest usable version of MSVC it finds in Program Files.

Optional:

- Microsoft Visual C++ 1.52 compiler and linker for MS-DOS targets.
  If present in C:\MSVC, make.bat will also generate libraries for DOS.
  Note that generating DOS versions is still more useful than it looks:
  Experience has shown that the severe memory constraints under DOS are a very
  good revelator of memory leaks, and other bad pointer issues. Build your 
  programs for DOS too if you can, and test them in a VM with Windows XP.
  This takes a very small extra build time. And it'll be very much worth the time
  if the Windows version appears to work, but the DOS version does not.
  Visual C++ 1.52 is available on the Visual Studio 2005 CD.
- The Visual C++ 8 compiler and tools from Microsoft Visual Studio 2005.
  This is the last version that allowed building programs for Windows 95/NT4.

The MsvcLibX.lib libraries are generated in subdirectories of src, then copied 
into the %BASEDIR%\MsvcLibX\lib directory, and renamed as shown in this table:

Subdirectory	 | Description				  | Renamed as
---------------- | -------------------------------------- | ----------------
DOS\BIN\T\	 | DOS normal version, tiny memory model  | MsvcLibXdt.lib
DOS\DEBUG\BIN\T\ | DOS debug version, tiny memory model	  | MsvcLibXdtd.lib
DOS\BIN\S\	 | DOS normal version, small memory model | MsvcLibXds.lib
DOS\DEBUG\BIN\S\ | DOS debug version, small memory model  | MsvcLibXdsd.lib
DOS\BIN\L\	 | DOS normal version, large memory model | MsvcLibXdl.lib
DOS\DEBUG\BIN\L\ | DOS debug version, large memory model  | MsvcLibXdld.lib
WIN95\		 | WIN32 normal version for Windows 95	  | MsvcLibXw32.lib
WIN95\DEBUG\	 | WIN32 debug version for Windows 95	  | MsvcLibXw32d.lib
WIN32\		 | WIN32 (X86) normal version		  | MsvcLibXw32.lib
WIN32\DEBUG\	 | WIN32 (X86) debug version		  | MsvcLibXw32d.lib
WIN64\		 | WIN64 (AMD64) normal version		  | MsvcLibXw64.lib
WIN64\DEBUG\	 | WIN64 (AMD64) debug version		  | MsvcLibXw64d.lib


Building programs using the MsvcLibX library
--------------------------------------------

Create a work directory, distinct from the MsvcLibX directories. Ex:

    set "HOME=%HOMEDRIVE%%HOMEPATH%"
    set "BASEDIR=%HOME%\Documents\SRC"
    md "%BASEDIR%\MyTools"
    cd "%BASEDIR%\MyTools"
    :# Define a variable giving the location of the MsvcLibX base directory
    :# (Automatically defined if you built the library already on that same system.)
    set "MSVCLIBX=%BASEDIR%\MsvcLibX"
    :# Get batch files and make files from MsvcLibX sources
    copy "%MSVCLIBX%\src\*.bat"
    copy "%MSVCLIBX%\src\*.mak"
    :# Create the configuration file (To be done just once)
    configure
    :# Compile and link your C or C++ program.
    :# Ex, for the dirc.c sample, to create all dirc.exe versions, type:
    make dirc.exe
    :# If there is any error, the dirc.log file will pop up.
    :# If there's no error, it's possible to check for warnings by reading dirc.log:
    notepad dirc.log
    :# All generated object files, listings, executables, etc, are in
    :# target-OS-specific subdirectories, like for the MsvcLibX builds above.
    :# They're automatically linked with the corresponding (renamed) MsvcLibX*.lib.

make.bat will generate WIN32 (X86) and WIN64 (AMD64) versions by default,
and put them respectively in the WIN32\ and WIN64\ subdirectories.  
It will also generate a DOS version in DOS\ if MSVC 1.52 is installed.  
It will also generate a WIN95 version in WIN95\ if MSVC 8 (aka. 2005) is installed.  
Run `make -?` get a help screen for make.bat.

Note that the configure.bat and make.bat scripts are actually independent of the
rest of the MsvcLibX library. They can be used to easily build any console 
programs for DOS and Windows, without loading the Visual Studio GUI.

An exe.bat script is a front-end to make.bat, saving a few characters to type:  
`exe dirc` <==> `make dirc.exe`


Building Linux versions of the same programs
--------------------------------------------

Install virtual machines with Linux, and give them access to the host's file
system, for example in the /c directory.  
Then execute the following commands, adapting the paths as needed:

    # Go to the work directory
    BASEDIR=/c/Users/YOURNAME/Documents/SRC
    mkdir $BASEDIR/MyTools
    cd $BASEDIR/MyTools
    # Get a bash script to build Linux versions using similar directory outputs 
    cp $BASEDIR/MsvcLibX/src/exe .
    # Make sure the Linux C compiler finds MsvcLibX debug macros, but not other MsvcLibX include files.
    # Important: Do not point C_INCLUDE_PATH at MsvcLibX/include, as this directory
    # contains duplicates for standard include files (Ex: stdio.h), that will fail
    # to compile in Linux.
    mkdir ~/include
    cp $BASEDIR/MsvcLibX/include/debugm.h ~/include
    export C_INCLUDE_PATH=~/include
    # Make sure that variable is defined in all future sessions
    echo "export C_INCLUDE_PATH=~/include" >>~/.bashrc
    # Compile your sample dirc.c program (which uses MsvcLibX debug macros)
    ./exe dirc
    # The output will be in subdirectories such as Linux.i686/ or Linux.x86_64/.
    # (The exact name depends on `echo "$(uname -s).$(uname -m)"` output)


Adding new files to the library
-------------------------------

All new files should have headers and comments similar to the existing ones.

To add a new source file (let's call it newfile.c) into the library:

- Put newfile.c in the %MSVCLIBX%\src directory.
- Add a +newfile.obj entry to the OBJECTS list in %MSVCLIBX%\src\Files.mak
- Also add a rule with newfile.c include files dependencies in src\Files.mak.
- Rebuild the library, and make sure there are no errors nor warnings.

To add a new include file into the library:

- All new include file names should be standard C library include files names!
- Put it in the include or include\sys subdirectory.

To add an include file overriding an homonym one in the MSVC library:

- The trick is to make it include MSVC's one, then define its own extensions.
  As MSVC compilers do not support the #include_next directive, I've implemented
  a mechanism for including MSVC include files using their full pathname.
  As an example, see include/direct.h or include/sys/stat.h.

  
The make file system
--------------------

Microsoft Visual Studio tools contain a build tool called nmake, very similar
to, but slightly incompatible with, Unix make.  
MsvcLibX's make.bat is designed to give a similar feel to Unix make.  
It uses internally a number of make files:

Make file   | Description
----------- | ----------------------------------------------------------------
NMakefile   | Default make file to use, if none is specified.
DOS.mak     | Generic rules for building MS-DOS programs into the DOS subdir.
WIN32.mak   | Generic rules for building 32-bits Windows programs into WIN32.
WIN64.mak   | Generic rules for building 64-bits Windows programs into WIN64.
WIN95.mak   | Generic rules for building Windows 95 programs into WIN95.
All.mak     | Generic rules for building one or more of the above.
Files.mak   | Application-specific source file dependancy rules. Intended to be includable from both Windows' nmakefile and Linux' makefile.

DOS.mak, WIN32.mak, WIN64.mak, and All.mak are pretty stable, and should not
be changed. The only likely case where a change is needed would be to add extra
libraries to link with _all_ programs.  
To add a library for one particular program, it'd be better to add a specific
rule in its own make file, as described below.  
In all cases, see the detailed notes in each make file header.

Specific make files:

To build a target called program.exe, the 5 make files with generic rules
(DOS.mak, WIN32.mak, WIN64.mak, WIN95.mak, and All.mak) first look for a 
specific make file called program.mak. They include it if present. This allows 
defining application-specific rules.  
These rules should use macros defined in the 4 make files to specify the
build environment and parameters. Here's a list of the most useful ones:

Macro     | Description
--------- | ----------------------------------------------------------------
T         | Target OS. One of DOS, WIN32, WIN64, WIN95.
S         | Path of the source files
O         | Path where to put the object files
B         | Path where to put the binary executable files
L         | Path where to put the listings
CFLAGS    | Flags for Microsoft C compiler
INCLUDE   | List of C include file paths, serarated by ';'
LFLAGS    | Flags for Microsoft linker
PROGRAM   | The program base name, infered from the target name.
SOURCES   | The list of sources for the program. Default: PROGRAM.c or .cpp
OBJECTS   | The list of objects to link. Default: PROGRAM.obj

Scripts:

Script                | Description
--------------------- | --------------------------------------------------------
make.bat	      | The main build tool. Invokes nmake.
config.%HOSTNAME%.bat | Defines paths to all tools used by make. Do not edit.
configure.bat 	      | Analyses your system, and generates a config.%HOSTNAME%.bat file.
configure.*.bat       | Define user or task-specific extensions to configure.bat.
exe.bat		      | Front end to make.bat, generating multiple goals.
exe		      | Linux shell script, invoking cc with multiple goals.
src2objs.bat	      | Internal script used by make files to convert SOURCES to OBJECTS

configure.bat with search for configure.*.bat scripts in %windir%, then in %HOME%,
then in the current directory.  
Put configuration scripts with your global preferences in %windir% for example.  
Within each directory, the files are called in the alphabetic order, allowing
to manage predictable dependancies.

Example 1: The 2clip program has no MS-DOS version. To prevent the make system
from attempting to build a DOS version (Only necessary if you DO have MSVC 1.52 
installed), create a 2clip.mak file with this content:

    !IF "$(T)"=="DOS"
    complain:
            @echo>con There's no DOS version of this program.
    
    dirs $(O)\2clip.obj $(B)\2clip.exe: complain
            @rem Do nothing
    !ENDIF

Example 2: Porting to Windows a resize.c program manipulating jpeg images,
and using the libjpeg library. Create a resize.mak file with lines like these:

    INCLUDE=$(INCLUDE);C:\JFL\SRC\Libs\libjpeg;C:\JFL\SRC\Libs\libjpeg\jpeg-8d
    LFLAGS=$(LFLAGS) C:\JFL\SRC\Libs\libjpeg\$(B)\libjpeg.lib

Example 3: Some Windows programs need to include additional resources, defined
in a .rc file. Ex: The update program uses a manifest to control its rights.
Create an update.mak file with directives like this:

    !IF "$(T)"=="WIN32" || "$(T)"=="WIN64"
    SOURCES=update.c update.rc
    LFLAGS=$(LFLAGS) /MANIFEST
    !ENDIF


The debug system
----------------

The MsvcLibX library makes it easy to build two versions of each program:

- A release version, small lean and fast.
- A debug version, with additional code to help developers debug the program.

It follows Microsoft's convention of defining the macro _DEBUG when compiling
a C/C++ source for a debug build.  
But it goes much further, by providing in debugm.h a set of macros to assist
debugging.

The general principle is that by default, the debug version operates exactly
like the release version. (Except possibly for performance)  
Then, if the "debug mode" is enabled, it outputs debug messages on stdout.
A major property of the MsvcLibX debugging output is that is is intended by
function call depth. This makes it considerably easier to read the debug output.

The MsvcLibX library itself is built in debug and release versions.
The make.bat system will link the release version of your program with the
release version of the MsvcLibX library, and likewise for the debug versions.  
To use it, include debugm.h in your main module, and add to your main() routine
a command-line option (-d or --debug maybe?) that calls DEBUG_ON().  
There's also an "extra debug mode", displaying even more details than the
debug mode. It is enabled by calling DEBUG_ON() twice. ==> Invoke with -d -d.

Debug macros:

Macro                       | Description
--------------------------- | ------------------------------------------------
DEBUG_ON()		    | Enable the debug mode.
DEBUG_CODE(...)		    | The code within parentheses is only compiled in the debug version
DEBUG_PRINTF((format, ...)) | Generates a printf instruction in the debug version only, that prints only if debug mode is enabled, with the output indented by call depth.
DEBUG_ENTER((format, ...))  | Like DEBUG_PRINTF, but for use at the beginning of a function. Increases the indent level.
DEBUG_LEAVE((format, ...))  | Like DEBUG_PRINTF, but for use before returning from a function. Decreases the indent level.
				
Note that every use of DEBUG_ENTER must be matched by one DEBUG_LEAVE. So if a
function has several return instructions, every return must be preceded by a
DEBUG_LEAVE.

DEBUG_LEAVE alternatives:  
To further simplify the source, a pair DEBUG_LEAVE()/return can be replaced by
one of the following macros:

Macro                         | Simplified description
----------------------------- | ------------------------------------------------
RETURN_INT(i)		      | DEBUG_LEAVE(("return %d\n", i)); return i;
RETURN_INT_COMMENT(i, (args)) | Idem, plus prints a comment behind the return
RETURN_BOOL(b)		      | DEBUG_LEAVE(("return %s\n", b?"TRUE":"FALSE")); return b;
RETURN_BOOL_COMMENT(b, (...)) | Idem, plus prints a comment behind the return
RETURN_CHAR(c)		      | DEBUG_LEAVE(("return %c\n", c)); return c;
RETURN_STRING(s)	      | DEBUG_LEAVE(("return %s\n", s)); return s;

For all the above, the release version just does return retValue;

Example for a recursive function factorial:

    int fact(int n) {
      DEBUG_ENTER((__FUNCTION__ "(%d);\n", n));
      if (n) n *= fact(n-1); else n = 1;
      RETURN_INT(n);
    }

The debug version, in debug mode, invoked with argument 4, prints:

    fact(4);
      fact(3);
        fact(2);
          fact(1);
            fact(0);
              return 1;
            return 1;
          return 2;
        return 6;
      return 24;


Support for UTF-8 sources
-------------------------

The MsvcLibX library supports writing C programs using 8-bit characters,
with strings encoded as UTF-8, and that will work for any cmd.exe code page.
This makes the sources much more simple and readable that using full-fledged
Unicode, with 16-bits wchar_t or WCHAR and L"strings" or _T("strings").

Note: The cmd.exe code page can be read and changed with the CHCP command.
The most common code pages are:

CP    | Description
----- | ----------------------------------------------------------------------------
437   | MS-DOS OEM code page, still used by cmd.exe in US and west-European systems.
1252  | Windows "ANSI" code page, used by most GUI programs, like notepad.exe.
65001 | UTF-8 code page. Allows display any Unicode character.

Important: Changing the code page will only work correctly if cmd.exe is using
a TrueType font. The default "Raster" font supports code page 437 only.

To enable that UTF-8 support:

1. Set the C or C++ source encoding to UTF-8 with BOM. (BOM = Byte-Order Mark)
Having a BOM is important, as without it some Windows editors will incorrectly
detect the encoding, and then sometimes corrupt the source.
2. Define one of the following constants in the .c source, _before_ including
any .h include files:

        #define _BSD_SOURCE  1	/* Defined by many standard BSD-Unix programs */
        #define _GNU_SOURCE  1	/* Defined by many standard GNU-Unix/Linux programs */
        #define _UTF8_SOURCE 1	/* MsvcLibX-specific */

Note that most modern Linux compilers do expect C sources encoded as UTF-8,
and will silently ignore the UTF-8 BOM if present.

Internally, MsvcLibX extends Microsoft's convention of having two ANSI and Wide
versions of each routine, respectively with an 'A' and a 'W' suffix. Ex:  
FindFirstFile() being an alias to either FindFirstFileA() or FindFirstFileW().  
MsvcLibX uses two additional suffixes: 'U' for the UTF-8 version, and 'M' for
the common MultiByte subroutine used by both the 'A' and 'U' versions. Ex:

Function   | Description
---------- | ---------------------------------------------------------------
readlinkW  | Posix routine readlink - Wide char version
readlinkM  | MultiByte char sub-routine, used by the next two routines.
readlinkA  | Posix routine readlink - ANSI version
readlinkU  | Posix routine readlink - UTF-8 version
readlink   | Posix routine readlink - Alias to either readlinkA or readlinkU

Note that the M version has one additional argument: The code page to use for
converting strings to and from Unicode. In that sense, it's not Posix-compliant.

Gotcha: As of 2014-03-25, most file I/O and enumeration routines have been
restructured this way, but a few have not yet been:  
scandir() and lstat() only support UTF-8 file names, not ANSI names.

Gotcha: As of 2014-03-25, there's a potential issue with the C main() routine:  
Supporting UTF-8 file names is not just supporting UTF-8 strings in library
functions. It's also necessary to process the command line, so that command line
arguments are passed in to the main() routine as UTF-8 strings.  
Currently this is implemented as a macro that redefines the main token, so
that it generates a main() routine just calling a _mainU0() routine from
MsvcLibX.lib, followed by another local _mainU() routine with the body intended
for your main routine. Ex:

    int main(int argc, char *argv[]) { /* your main body */ }

Becomes:

    int main(int argc, char *argv[]) {return _mainU0()}
    int _mainU(int argc, char *argv[]) { /* your main body */ }

The _mainU0() routine from MsvcLibX.lib reprocesses the Win32 command line as
UTF-8 argv[] arguments, then calls _mainU(argc, argv[]).  
This works well and transparently, except in one case:  
If one of your sources or include files contain a prototype for the main() 
routine, then MsvcLibX' main macro will break that prototype, and cause
compilation and/or link errors.  
If this happens, simply remove the main() prototype, which is useless anyway.


Support for NTFS symlinks and junctions
---------------------------------------

Posix defines only a single kind of symbolic links, usable for any kind of
targets, whether they're files, directories, or further symbolic links.
The standard C library defines functions for managing symbolic links:

Function   | Description
---------- | ----------------------------------------------------------------
readlink() | Read a link target
symlink()  | Create a link, or change its target
lstat()    | Read the metadata (timestamp, access rights) for the link itself
lchmod()   | Change the link access rights
lchown()   | Change the link owner
realpath() | Generate an absolute path, with all links resolved

Windows defines three types of links:

Type      | Description
--------- | ---------------------------------------------------------------
SYMLINK	  | Symbolic link to a file
SYMLINKD  | Symbolic link to a directory
JUNCTION  | Mount point, often used as a symbolic link to another directory

All three types can be created in Vista and later by the mklink command.
JUNCTIONS can also be created in 2000 and later by Microsoft's SysInternal's
junction command.  
One important difference is that JUNCTIONs can be created with normal user
rights, whereas SYMLINKs and SYMLINKDs require administrator rights in an 
elevated command window.  
A second important difference is that on networks, SYMLINKs and SYMLINKDs are
interpreted on the client side, whereas JUNCTIONs are interpreted on the server
side (despite having their target readable from the client side).

The MsvcLibcX library tries to hide that complexity, and implements the standard
functions as if there were only one kind of link.  
It also provides non-standard functions symlinkd() and junction() to
specifically create SYMLINKDs and JUNCTIONs respectively.

Notes about readlink():  
For SYMLINKs and SYMLINKDs, the case is straightforward.  
For JUNCTIONs, there are two problems:

- The target is stored as an absolute path, even when the JUNCTION was created
  with a relative path. readlink() tries to convert the absolute path to a
  relative path, so that file copying utilities can clone trees with internal
  JUNCTIONs.
- When the JUNCTION is on a network drive, the target refers to the absolute
  path on the server. This may not be accessible from the client through the
  existing mounted shares. Even when this is accessible, it's not always easy
  to map the server path to a valid client path.  
  readlink() uses heuristics which always work for drives shared at the drive
  level. Ex: a C: drive shared as C$, a D: drive shared as D$, etc.  
  The heuristic also very likely works for drives shared at the root or first
  directory level. Ex: C:\ shared as CROOT, or C:\Public shared as PUBLIC.
  As of 2014-03-25, it'll fail in any other case. Ex:  
  C:\Users\YOURNAME shared as YOURHOME, 
  or a C:\Public share mounted through its subdirectory C:\Public\Temp

Notes about symlink():  
symlink() will attempt to create a SYMLINK or a SYMLINKD, depending on the type
of the target. This works well when the target exists. But when it does not
(which is legal), it will create a SYMLINK by default, or a SYMLINKD if the
target ends with a '/' or a '\'. Posix allows, but does not require, providing
a trailing '/', so the link type may possibly be incorrect.  
junction() will have the same issues as readlink() above.

Notes about junction():  
The problem for junction() is to convert a client-side target pathname provided
by the program running on the client, to a server-side pathname, necessary for
junctions to work.  
For full-drive shares (i.e. any share named like D$), this is easy.  
For non-full-drive shares (i.e. anything else), it will assume this is a
first level shared directory on the C: drive. Ex: A link on share PUBLIC
will be targeted at C:\PUBLIC.  
Problem: The junction will not work if the share actually resides anywhere else
on the server. But, surprisingly, there's an easy workaround:  
Simply create manually on the server itself, a junction called C:\PUBLIC,
pointing at the actual directory shared as PUBLIC.  
This way the junctions created from the client side will work correctly, both
on the client and on the server side, after being resolved on the server side
through that second junction.


Support for Windows 95/98
-------------------------

The configure.bat script searches for old versions of the Visual C++ compiler,
which can build WIN32 programs that can run in Windows 95/98/ME/NT4.  
The most recent of these is Visual C++ 8, from Visual Studio 2005.  
The make.bat script can then use rules in win95.mak to builds WIN32 programs
that will run in any version of Windows from Windown 95 to Windows 10.

Note however that Windows 95/98/ME only have a very limited support for Unicode
built in. The rest of this section mentions 95, but applies to 98 & ME as well.
The MsvcLibX library uses a number of Unicode functions not available in default
installations of Windows 95. This includes all file management functions.  
Thus most of our WIN95 executables will not work by default in Windows 95.  
To allow them to work, it is necessary to download from Microsoft a "Microsoft
Layer for Unicode on Windows 95/98/ME Systems" (MSLU for short), and install it
on the Windows 95 system. See the following links for details:  
https://en.wikipedia.org/wiki/Microsoft_Layer_for_Unicode  
https://msdn.microsoft.com/en-us/goglobal/bb688166.aspx  
MSLU installation procedure:  

- Download the MSLU redistributable setup (unicows.exe) from:
  http://go.microsoft.com/fwlink/?LinkId=14851
- Extract unicows.dll from the unicows.exe archive.
- Copy that unicows.dll to the Windows 95 system, into %windir%\System.

Testing WIN95 executables in a Windows 95 VM  
VMWare Player does not have Windows 95 drivers for the HGFS file system.
This prevents accessing the host's files directly as network files, as is
usually done for Windows XP and later versions of Windows.  
It is not possible to use network shares either, as Windows 95 only supports
the SMB 1 protocol, which is actively blocked by Windows Vista and later hosts.
It is possible, but inconvenient, to transit through a web server, and download
the files in the Windows 95 VM using Internet Explorer 4.  
The best solution probably is to transit through a floppy or CD image, and
mount that image in the VM Player. Many tools, including our own HpMkIso.exe
can create CD images. A very convenient shareware called WinImage allows to
create floppy images.  
Another solution is to install a Web server on the host PC, and use Internet
Explorer 4 in Windows 95 to download the executable files into the VM.


Support for DOS, and bound DOS+Windows programs
-----------------------------------------------

- If Visual C++ 1.52 is installed, configure.bat will setup the make system
for building the MS-DOS version of your programs. (Output in the DOS directory)  
- If Visual C++ 8 is installed, configure.bat will setup the make system
for building 32-bits versions of your programs compatible with Windows 95
and all later versions, including 64-bits ones. (Output in the WIN95 directory)  

Both are available as part of the Visual Studio 2005 CD, still available for
download for MSDN subscribers from the MSDN web site.

Win32 programs have an "MS-DOS stub", that runs when the Windows program is
executed under MS-DOS.  
The default stub used by the Win32 linker if a tiny DOS program that displays
an error message such as: "This program can only run in Windows"

When it builds the WIN95 or WIN32 version of a program, and when it has built
the DOS version already, the MsvcLibX make system uses that DOS version as the
stub for the Windows version.  
This allows building executables that work in *all* versions of DOS and Windows!

- When run in MS-DOS, it's the DOS stub of the exe that runs.
- When run in Windows (even 64-bits versions), it's the Win32 part that runs.

Note that the make system will build such bound executables for any WIN32
build made with more recent compilers. But these recent compilers generate
executables that cannot run in old versions of Windows. For example, the
Visual C++ 14 compiler can only target Windows Vista and later systems.
Having an executable that can run in DOS and Windows 7, but not in Windows XP,
is not very useful. Make sure to install the Visual C++ 8 compiler in parallel
with Visual C++ 1.52, and the latest compiler (Visual C++ 14 at the time of 
this writing), to generate truly universal WIN95 builds, that run in 
DOS/95/98/ME/2000/XP/Vista/7/8/10.


History
-------

**1986**

I (Jean-François Larvoire) started writing command-line tools for MS-DOS.
Some were enumerating files, using inline assembly language to make MS-DOS
interrupt 21h system calls: update, dirsize, redo, backnum, which, dirc...  
To make it simple I factored these out in subroutines srch1st and srchnext,
that I manually copied from one program to the next.  
Things got a bit tricky to support recursion, which was not straightforward
in MS-DOS.


**1992**

We got an OS/2 server, and I started porting the above programs to OS/2.
MS-DOS was still important, so I used conditional compilation to support
both operating systems with the same source.  
I wrote a second version of srch1st and srchnext for OS/2, and had to
include a new routine srchdone due to OS/2 API constraints.  
dirc was the first program I ported, then I slowly duplicated the code into
the other programs. Synchronizing bug fixes became more difficult.  
A nice trick was the OS/2 supported dual-mode EXEs, with both the DOS and
OS/2 version bound in the same .exe file.


**1995**

We ditched the OS/2 server, and got a new one running Windows NT.  
Again, I created a third conditionally compiled version of srch1st/srchnext/
srchdone for WIN32, for use in dirc.  
Manually back porting the updates and bug fixes to all programs became
really painful, and took several years.  
Like OS/2, Windows supported dual-mode EXEs, and I updated my make files
to include both the DOS and Windows version in the same file.


**2005**

I started working on Linux projects. Despite the bonanza of command-line
tools available, I couldn't find one equivalent to dirc.  
So, yet another time, I created a fourth conditionally compiled version of
srch1st/srchnext/srchdone for Linux, and obtained a Linux version of dirc.
I also ported it and a couple of other programs to Tru64, which was the
first 64-bits OS I worked with. This exposed a few unsuspected bugs.  
The thing became so complex than porting the changes and updates to the
other programs was a nightmare. I did it for a few of them, but never
got the time to port them all.


**2010**

Building WIN64 versions was relatively easier due to the Tru64 precedent,
but added yet another set of conditional compilations.   
The porting nightmare worsened.


**2012**

I tried porting some unrelated Linux programs to Windows, and hit a wall:
Many include files and standard C library routines were missing in MSVC.
I then tried using MinGW, but it too was missing many required features!
I considered contributing updates to MinGW, but that project was too
complex and ill-documented at that time, and I eventually gave up.  
Instead, I started writing my own "libc-ext" library of include files and
routines to supplement MSVC.  
Ex: stdint.h, inttypes.h, fnmatch.h/fnmatch.c, ...  
Also it became obvious that multiplying conditional compilations and 
duplicating directory access code everywhere was wrong. Instead I had to
write standard dirent.h/dirent.c routines for DOS/OS2/Windows, and
rewrite all my programs around these standard routines.  
I did it for DOS and Windows versions, and left stubs of the OS/2 versions,
for the unlikely case where somebody wants to revive them.

**2013**

The restructuration was over for dirc, dirsize, which, backnum, update.
The library got its final name, "MsvcLibX", to better match it purpose:  
An extension of the Microsoft Visual C library, not of the standard libc.  
As the library grew, debugging it became more difficult, and I decided to
use my debugm.h within the library: This file contains a set of debugging
macros I had developed for other programs.  
I started thinking about sorely needed improvements:

- There was no support for Windows symlinks and junctions.
- The Windows versions of the programs output ANSI file names into a
  cmd.exe window using the OEM character set. This caused all files with
  French names to be shown as garbage.
- Worse still, I had a few files and directories with non-ANSI names
  (In Russian and Chinese), that caused the programs to fail!

The Linux version of the program did not have these issues, as all recent
versions of Linux use the UTF-8 encoding, and this works transparently
even for old programs using 8-bits characters like mine.


**2014**

I got a bit more time, and started working on a redesign of MsvcLibX's
dirent.c/dirent.h, and added lstat.c, symlink.c, readlink.c, etc, to
support symlinks, junctions, and UTF-8 file names.  
This proved to be much more work than I initially thought, but the result
was worth the effort: dirc, update got easily adapted, with remarkably
few changes to their source. Adding recursion to update was easy.  
I'm now able to use update to backup all files on my system, including
symbolic links, and junctions used as poor man's links. And the programs
now display names correctly in any code page with the right font.  
A seventh program, truename, joined the collection using dirent.h routines.
Later in the year, I made significant other changes:

- Split make.bat into a generic make.bat/configure.bat pair of scripts.
  configure.bat needs to be run once, plus everytime the environment
  changes. (Such as if a new MSVC version is installed.)
  Project-specific definitions are moved to new files, such as our
  configure.MsvcLibX.bat.
- Added a general mechanism for defining extensions to existing MSVC
  include files. This allowed defining our own homonym include files,
  containing just the missing definitions. Which in turn allowed to move
  many such definitions, that were initially stored in unistd.h for lack
  of an alternative, to their standard location.
- Updated all file functions to support WIN32 pathnames > 260 characters.
  (The basic WIN32 functions that I used until then had that limitation;
  I'm now using extended functions supporting path lengths up to 64K.)

All tools like dirc, dirsize, which, backnum, update, truename, redo
benefit from that last change.

**2015**

A major improvement was the addition of support for new operating systems
and processor targets. This required redesigning several things:  
The OS-specific definition macros have been renamed to more generic names.
The DosWin.mak file has been replaced by a more generic All.mak,
supporting the old dos.mak, win32.mak, and win64.mak, plus the new...

- bios.mak     Allows building 16-bits programs that can run in BIOS option
               ROMs. These programs are based on the BiosLib library,
               documented separately.
- win95.mak    Allows building win32 programs that run in Windows 95.
- ia64.mak     Allows building 64-bits programs that run in IA64 versions
	       of Windows. Not tested.
- arm.mak      Allows building win32 programs for Windows RT.
	       Tests failed so far, due to a missing "ARM Desktop SDK".

All.mak also skips building versions for which no tools are available;
This prevents problems in the normal case when people only have the latest
version of MSVC. In this case, it just builds the WIN32 and WIN64 versions.
The support for Windows 95 required fixing numerous issues with old
Microsoft tools and Windows SDKs.  
Conversely, the support for Visual Studio 15 also required fixing lots of
issues, as the MSVC library has been completely redesigned, and split into
two parts:

- A compiler-specific part, part of the compiler tree as before.
- A generic part, called Universal C runtime (UCRT) that's now part of
  the windows SDK.

And of course there were also issues with MsvcLibX recent improvements,
like Unicode support and symlink support, which had never been tested,
and of course did not work, in Windows 95 and XP.


**2016**

Many significant changes and improvements this year:

- Changed the UTF-8 C source support to require a UTF-8 BOM.  
  This is to prevent problems with Windows tools that tend to corrupt files
  without a UTF-8 BOM, but with other UTF-8 characters.  
  This required changing all C/C++ compilation rules to first remove the
  UTF-8 BOM, as MS compilers do not react correctly when they find one.
- Added a windows.h extension.
  Just like Standard C library APIs, windows 8-bit APIs can be overriden to
  refer to custom routines that support UTF-8 strings.  
  The MsvcLibX library was beginning to use a significant number of these
  custom routines internally. They're now accessible directly to outside
  UTF-8 programs targeting only Windows.
- Finished implementing support for the OUTDIR variable. (Started in 2015.)
  All make files now optionally create output files in an %OUTDIR% directory.
  This is intended for testing builds in VMs, with shared sources on the
  host, but the output locally in the VM, avoiding to overwrite the main
  version on the host. IF %OUTDIR% is not defined, the default output 
  still goes below the source directory as before.