]> asedeno.scripts.mit.edu Git - PuTTY.git/blobdiff - mkfiles.pl
first pass
[PuTTY.git] / mkfiles.pl
index 46ae3189985639de744429c174763db9a6203e88..ae15ac488d66caec8b68db0c021c490058b4d2d9 100755 (executable)
@@ -47,8 +47,8 @@ open IN, "Recipe" or do {
 # HACK: One of the source files in `charset' is auto-generated by
 # sbcsgen.pl, and licence.h is likewise generated by licence.pl. We
 # need to generate those _now_, before attempting dependency analysis.
-eval 'chdir "charset"; require "sbcsgen.pl"; chdir ".."; select STDOUT;';
-eval 'require "licence.pl"; select STDOUT;';
+eval 'chdir "charset"; require "./sbcsgen.pl"; chdir ".."; select STDOUT;';
+eval 'require "./licence.pl"; select STDOUT;';
 
 @srcdirs = ("./");
 
@@ -84,7 +84,15 @@ while (<IN>) {
   if ($_[0] eq "!specialobj" and &mfval($_[1])) { $specialobj{$_[1]}->{$_[2]} = 1; next;}
   if ($_[0] eq "!cflags" and &mfval($_[1])) {
       ($rest = $_) =~ s/^\s*\S+\s+\S+\s+\S+\s*//; # find rest of input line
-      $rest = 1 if $rest eq "";
+      if ($rest eq "") {
+          # Make sure this file doesn't get lumped together with any
+          # other file's cflags.
+          $rest = "F" . $_[2];
+      } else {
+          # Give this file a specific set of cflags, but permit it to
+          # go together with other files using the same set.
+          $rest = "C" . $rest;
+      }
       $cflags{$_[1]}->{$_[2]} = $rest;
       next;
   }
@@ -261,7 +269,7 @@ sub mfval($) {
     # prints a warning and returns false;
     if (grep { $type eq $_ }
        ("vc","vcproj","cygwin","borland","lcc","devcppproj","gtk","unix",
-         "am","osx","vstudio10","vstudio12")) {
+         "am","osx","vstudio10","vstudio12","clangcl")) {
         return 1;
     }
     warn "$.:unknown makefile type '$type'\n";
@@ -430,13 +438,135 @@ $orig_dir = cwd;
 
 # Now we're ready to output the actual Makefiles.
 
+if (defined $makefiles{'clangcl'}) {
+    $dirpfx = &dirpfx($makefiles{'clangcl'}, "/");
+
+    ##-- Makefile for cross-compiling using clang-cl, lld-link, and
+    ##   MinGW's windres for resource compilation.
+    #
+    # This makefile allows a complete Linux-based cross-compile, but
+    # using the real Visual Studio header files and libraries. In
+    # order to run it, you will need:
+    #
+    #  - MinGW windres on your PATH.
+    #     * On Ubuntu as of 16.04, you can apt-get install
+    #       binutils-mingw-w64-x86-64 and binutils-mingw-w64-i686
+    #       which will provide (respectively) 64- and 32-bit versions,
+    #       under the names to which RCCMD is defined below.
+    #  - clang-cl and lld-link on your PATH.
+    #     * I built these from the up-to-date LLVM project trunk git
+    #       repositories, as of 2017-02-05.
+    #  - case-mashed copies of the Visual Studio include directories.
+    #     * On a real VS installation, run vcvars32.bat and look at
+    #       the resulting value of %INCLUDE%. Take a full copy of each
+    #       of those directories, and inside the copy, for each
+    #       include file that has an uppercase letter in its name,
+    #       make a lowercased symlink to it. Additionally, one of the
+    #       directories will contain files called driverspecs.h and
+    #       specstrings.h, and those will need symlinks called
+    #       DriverSpecs.h and SpecStrings.h.
+    #     * Now, on Linux, define the environment variable INCLUDE to
+    #       be a list, separated by *semicolons* (in the Windows
+    #       style), of those directories, but before all of them you
+    #       must also include lib/clang/5.0.0/include from the clang
+    #       installation area (which contains in particular a
+    #       clang-compatible stdarg.h overriding the Visual Studio
+    #       one).
+    #  - similarly case-mashed copies of the library directories.
+    #     * Again, on a real VS installation, run vcvars32 or
+    #       vcvarsx86_amd64 (as appropriate), look at %LIB%, make a
+    #       copy of each directory, and provide symlinks within that
+    #       directory so that all the files can be opened as
+    #       lowercase.
+    #     * Then set LIB to be a semicolon-separated list of those
+    #       directories (but you'll need to change which set of
+    #       directories depending on whether you want to do a 32-bit
+    #       or 64-bit build).
+    #  - for a 64-bit build, set 'Platform=x64' in the environment as
+    #    well, or else on the make command line.
+    #     * This is a variable understood only by this makefile - none
+    #       of the tools we invoke will know it - but it's consistent
+    #       with the way the VS scripts like vcvarsx86_amd64.bat set
+    #       things up, and since the environment has to change
+    #       _anyway_ between 32- and 64-bit builds (different set of
+    #       paths in $LIB) it's reasonable to have the choice of
+    #       compilation target driven by another environment variable
+    #       set in parallel with that one.
+
+    open OUT, ">$makefiles{'clangcl'}"; select OUT;
+    print
+    "# Makefile for cross-compiling $project_name using clang-cl, lld-link,\n".
+    "# and MinGW's windres, using GNU make on Linux.\n".
+    "#\n# This file was created by `mkfiles.pl' from the `Recipe' file.\n".
+    "# DO NOT EDIT THIS FILE DIRECTLY; edit Recipe or mkfiles.pl instead.\n";
+    print $help;
+    print
+    "\n".
+    "CCCMD = clang-cl\n".
+    "ifeq (\$(Platform),x64)\n".
+    "CCTARGET = x86_64-pc-windows-msvc18.0.0\n".
+    "RCCMD = x86_64-w64-mingw32-windres\n".
+    "else\n".
+    "CCTARGET = i386-pc-windows-msvc18.0.0\n".
+    "RCCMD = i686-w64-mingw32-windres\n".
+    "endif\n".
+    "CC = \$(CCCMD) --target=\$(CCTARGET)\n".
+    &splitline("RC = \$(RCCMD) --preprocessor=\$(CCCMD) ".
+               "--preprocessor-arg=/TC --preprocessor-arg=/E")."\n".
+    "LD = lld-link\n".
+    "\n".
+    "# C compilation flags\n".
+    &splitline("CFLAGS = /nologo /W3 /O1 " .
+               (join " ", map {"-I$dirpfx$_"} @srcdirs) .
+               " /D_WINDOWS /D_WIN32_WINDOWS=0x500 /DWINVER=0x500 ".
+               "/D_CRT_SECURE_NO_WARNINGS")."\n".
+    "LFLAGS = /incremental:no /dynamicbase /nxcompat\n".
+    &splitline("RCFLAGS = ".(join " ", map {"-I$dirpfx$_"} @srcdirs).
+               " -DWIN32 -D_WIN32 -DWINVER=0x0400")."\n".
+    "\n".
+    &def($makefile_extra{'clangcl'}->{'vars'}) .
+    "\n".
+    "\n";
+    print &splitline("all:" . join "", map { " \$(BUILDDIR)$_.exe" } &progrealnames("G:C"));
+    print "\n\n";
+    foreach $p (&prognames("G:C")) {
+       ($prog, $type) = split ",", $p;
+       $objstr = &objects($p, "\$(BUILDDIR)X.obj", "\$(BUILDDIR)X.res.o", undef);
+       print &splitline("\$(BUILDDIR)$prog.exe: " . $objstr), "\n";
+
+       $objstr = &objects($p, "\$(BUILDDIR)X.obj", "\$(BUILDDIR)X.res.o", "X.lib");
+       $subsys = ($type eq "G") ? "windows" : "console";
+       print &splitline("\t\$(LD) \$(LFLAGS) \$(XLFLAGS) ".
+                         "/out:\$(BUILDDIR)$prog.exe ".
+                         "/lldmap:\$(BUILDDIR)$prog.map ".
+                         "/subsystem:$subsys\$(SUBSYSVER) $objstr")."\n\n";
+    }
+    foreach $d (&deps("\$(BUILDDIR)X.obj", "\$(BUILDDIR)X.res.o", $dirpfx, "/", "vc")) {
+        $extradeps = $forceobj{$d->{obj_orig}} ? ["*.c","*.h","*.rc"] : [];
+        print &splitline(sprintf("%s: %s", $d->{obj},
+                                 join " ", @$extradeps, @{$d->{deps}})), "\n";
+        if ($d->{obj} =~ /\.res\.o$/) {
+            print "\t\$(RC) \$(RCFLAGS) ".$d->{deps}->[0]." -o ".$d->{obj}."\n\n";
+       } else {
+            print "\t\$(CC) /Fo\$(BUILDDIR) \$(COMPAT) \$(CFLAGS) \$(XFLAGS) /c \$<\n\n";
+        }
+    }
+    print "\n";
+    print &def($makefile_extra{'clangcl'}->{'end'});
+    print "\nclean:\n".
+        &splitline("\trm -f \$(BUILDDIR)*.obj \$(BUILDDIR)*.exe ".
+                   "\$(BUILDDIR)*.res.o \$(BUILDDIR)*.map ".
+                   "\$(BUILDDIR)*.exe.manifest")."\n";
+    select STDOUT; close OUT;
+}
+
 if (defined $makefiles{'cygwin'}) {
     $dirpfx = &dirpfx($makefiles{'cygwin'}, "/");
 
-    ##-- CygWin makefile
+    ##-- MinGW/CygWin makefile (called 'cygwin' for historical reasons)
     open OUT, ">$makefiles{'cygwin'}"; select OUT;
     print
-    "# Makefile for $project_name under Cygwin, MinGW, or Winelib.\n".
+    "# Makefile for $project_name under MinGW, Cygwin, or Winelib.\n".
     "#\n# This file was created by `mkfiles.pl' from the `Recipe' file.\n".
     "# DO NOT EDIT THIS FILE DIRECTLY; edit Recipe or mkfiles.pl instead.\n";
     # gcc command line option is -D not /D
@@ -447,6 +577,7 @@ if (defined $makefiles{'cygwin'}) {
     "# You can define this path to point at your tools if you need to\n".
     "# TOOLPATH = c:\\cygwin\\bin\\ # or similar, if you're running Windows\n".
     "# TOOLPATH = /pkg/mingw32msvc/i386-mingw32msvc/bin/\n".
+    "# TOOLPATH = i686-w64-mingw32-\n".
     "CC = \$(TOOLPATH)gcc\n".
     "RC = \$(TOOLPATH)windres\n".
     "# Uncomment the following two lines to compile under Winelib\n".
@@ -455,11 +586,11 @@ if (defined $makefiles{'cygwin'}) {
     "# You may also need to tell windres where to find include files:\n".
     "# RCINC = --include-dir c:\\cygwin\\include\\\n".
     "\n".
-    &splitline("CFLAGS = -mno-cygwin -Wall -O2 -D_WINDOWS -DDEBUG -DWIN32S_COMPAT".
-      " -D_NO_OLDNAMES -DNO_MULTIMON -DNO_HTMLHELP -DNO_SECUREZEROMEMORY " .
+    &splitline("CFLAGS = -Wall -O2 -D_WINDOWS -DDEBUG -DWIN32S_COMPAT".
+      " -D_NO_OLDNAMES " .
               (join " ", map {"-I$dirpfx$_"} @srcdirs)) .
               "\n".
-    "LDFLAGS = -mno-cygwin -s\n".
+    "LDFLAGS = -s\n".
     &splitline("RCFLAGS = \$(RCINC) --define WIN32=1 --define _WIN32=1 ".
       "--define WINVER=0x0400 ".(join " ", map {"-I$dirpfx$_"} @srcdirs))."\n".
     "\n".
@@ -636,8 +767,8 @@ if (defined $makefiles{'vc'}) {
       "# C compilation flags\n".
       "CFLAGS = /nologo /W3 /O1 " .
       (join " ", map {"-I$dirpfx$_"} @srcdirs) .
-      " /D_WINDOWS /D_WIN32_WINDOWS=0x500 /DWINVER=0x500\n".
-      "LFLAGS = /incremental:no /fixed\n".
+      " /D_WINDOWS /D_WIN32_WINDOWS=0x500 /DWINVER=0x500 /D_CRT_SECURE_NO_WARNINGS\n".
+      "LFLAGS = /incremental:no /dynamicbase /nxcompat\n".
       "RCFLAGS = ".(join " ", map {"-I$dirpfx$_"} @srcdirs).
       " -DWIN32 -D_WIN32 -DWINVER=0x0400\n".
       "\n".
@@ -667,7 +798,7 @@ if (defined $makefiles{'vc'}) {
            print "$objlines[$i]\n";
        }
        print "<<\n";
-       print "\tlink \$(LFLAGS) \$(XLFLAGS) -out:\$(BUILDDIR)$prog.exe -map:\$(BUILDDIR)$prog.map -nologo -subsystem:$subsys \@$inlinefilename\n\n";
+       print "\tlink \$(LFLAGS) \$(XLFLAGS) -out:\$(BUILDDIR)$prog.exe -map:\$(BUILDDIR)$prog.map -nologo -subsystem:$subsys\$(SUBSYSVER) \@$inlinefilename\n\n";
     }
     foreach $d (&deps("\$(BUILDDIR)X.obj", "\$(BUILDDIR)X.res", $dirpfx, "\\", "vc")) {
         $extradeps = $forceobj{$d->{obj_orig}} ? ["*.c","*.h","*.rc"] : [];
@@ -1508,7 +1639,8 @@ if (defined $makefiles{'am'}) {
     # auto-generated parts of this makefile, but Recipe might like to
     # have it available as a variable so that mandatory-rebuild things
     # (version.o) can conveniently be made to depend on it.
-    @sources = ("allsources", "=", sort keys %allsourcefiles);
+    @sources = ("allsources", "=",
+                sort grep {$_ ne "empty.h"} keys %allsourcefiles);
     print &splitline(join " ", @sources), "\n\n";
 
     @cliprogs = ("bin_PROGRAMS", "=");
@@ -1528,11 +1660,20 @@ if (defined $makefiles{'am'}) {
     print "endif\n\n";
 
     @noinstcliprogs = ("noinst_PROGRAMS", "=");
-    foreach $p (&prognames("XT:UT")) {
+    foreach $p (&prognames("UT")) {
       ($prog, $type) = split ",", $p;
       push @noinstcliprogs, $prog;
     }
+    @noinstallprogs = @noinstcliprogs;
+    foreach $p (&prognames("XT")) {
+      ($prog, $type) = split ",", $p;
+      push @noinstallprogs, $prog;
+    }
+    print "if HAVE_GTK\n";
+    print &splitline(join " ", @noinstallprogs), "\n";
+    print "else\n";
     print &splitline(join " ", @noinstcliprogs), "\n";
+    print "endif\n\n";
 
     %objtosrc = ();
     foreach $d (&deps("X", undef, "", "/", "am")) {
@@ -1552,9 +1693,11 @@ if (defined $makefiles{'am'}) {
 
     %amspeciallibs = ();
     foreach $obj (sort { $a cmp $b } keys %{$cflags{'am'}}) {
+      my $flags = $cflags{'am'}->{$obj};
+      $flags = "" if $flags !~ s/^C//;
       print "lib${obj}_a_SOURCES = ", $objtosrc{$obj}, "\n";
       print &splitline(join " ", "lib${obj}_a_CFLAGS", "=", @amcflags,
-                       $cflags{'am'}->{$obj}), "\n";
+                       $flags), "\n";
       $amspeciallibs{$obj} = "lib${obj}.a";
     }
     print &splitline(join " ", "noinst_LIBRARIES", "=",