#! /usr/bin/perl -w # # Generates djgpp/Unix/Mingw32 makefiles, Watcom and MSVC batch files, # and an MSVC version 6 project file (.dsp) for building portable # libraries, reading info about them from the buildlib.in file. # # By George Foot, October 2000. # # Based on `builder.pl' by Shawn Hargreaves, December 1999. # my filename $me = $0; $me =~ s,.*/,,; # builder file directory $build = $0; $build =~ s,(.*)/.*,$1,; # project configuration file $in = "$build/$me"; $in =~ s/(.*)\.[^\.]*/$1.in/; print "Reading $in\n"; open FILE, "$in" or die "\nError: can't open $in:\n $!"; while () { s/#.*//; if (/\s*([^=]*\S)\s*=\s*(.*)/) { $param{$1} = $2; } } close FILE; die "Error: NAME not set in $in" unless ($param{"NAME"}); die "Error: OBJDIR not set in $in" unless ($param{"OBJDIR"}); die "Error: LIBDIR not set in $in" unless ($param{"LIBDIR"}); # check whether we should clean up a bit if (defined $ARGV[0] and $ARGV[0] eq "clean") { print "Removing build files...\n"; unlink "$build/makefile.all", "$build/makefile.dj", "$build/makefile.uni", "$build/makefile.mgw", "$build/clean.bat", "$build/$param{'NAME'}.dsp", "$build/msvcmake.bat", "$build/watmake.bat", "fixdjgpp.bat", "fixwat.bat", "fixunix.sh", "fixmsvc.bat", "fixmingw.bat", "makefile", "makefile.all", "clean.bat", "msvcmake.bat", "$param{'NAME'}.dsp"; exit; } # import package settings foreach $package (split (" ", $param{"PACKAGES"})) { $in = "$build/$package.pkg"; print "Reading $in\n"; open FILE, "$in" or die "\nError: can't open $in:\n $!"; while () { s/#.*//; if (/\s*([^=]*\S)\s*\+=\s*(.*)/) { $param{$1} .= " $2"; } elsif (/\s*([^=]*\S)\s*=\s*(.*)/) { $param{$1} = $2; } } close FILE; } # convert obj and bin paths to pretty formats $dosobj = $unixobj = $param{"OBJDIR"}; $doslib = $unixlib = $param{"LIBDIR"}; # get slashes the right way around $dosobj =~ s/\//\\/g; $doslib =~ s/\//\\/g; $unixobj =~ s/\\/\//g; $unixlib =~ s/\\/\//g; # strip trailing slashes $dosobj =~ s/\\$//; $doslib =~ s/\\$//; $unixobj =~ s/\/$//; $unixlib =~ s/\/$//; print "\n"; # scans a source file for dependency information sub get_dependencies { my $filename = shift; return if ($depends{$filename}); # scan the file for include statements open FILE, $filename or die "\nError opening $filename:\n $!"; my @deps = (); while () { # strip comments s/\/\/.*//; s/\/\*.*\*\///g; if (/^\s*#include\s*[<"](.*)[>"]/) { push @deps, $1; } } close FILE; # build the dependency list $depends{$filename}{$filename} = 1; for my $header (@deps) { my $head = $header; $head =~ s/\\/\//g; if ($filename =~ /(.*[\\\/])/) { $head = $1 . $head; } if (-f $head) { # recurse into a header $headers{$head} = 1; $depends{$filename}{$head} = 1; get_dependencies($head); for (keys %{$depends{$head}}) { $depends{$filename}{$_} = 1; } } else { $unresolved{$header} = 1; } } } # scan for source files sub scan_directory { my $dir = shift; for my $filename (<$dir*>) { if (-d $filename) { # recurse into a directory scan_directory("$filename/"); } elsif ($filename =~ /\.(c|cpp)$/) { # got a source file print " $filename\n"; $cplusplus = 1 if ($1 eq "cpp"); $sources{$filename} = 1; get_dependencies($filename); } } } # initiate the recursive directory scan print "Looking for source files...\n"; if (exists $param{"SRCDIR"}) { scan_directory($param{"SRCDIR"}); } else { scan_directory(""); } print "\n"; # warn about any unresolved headers %standard_headers = ( "assert.h" => 1, "ctype.h" => 1, "errno.h" => 1, "fcntl.h" => 1, "limits.h" => 1, "locale.h" => 1, "malloc.h" => 1, "math.h" => 1, "memory.h" => 1, "search.h" => 1, "setjmp.h" => 1, "signal.h" => 1, "stdarg.h" => 1, "stdio.h" => 1, "stdlib.h" => 1, "string.h" => 1, "sys/stat.h" => 1, "sys/timeb.h" => 1, "sys/types.h" => 1, "time.h" => 1, ); if ($unresolved) { print "Warning: project uses non-standard header files:\n"; for (sort keys %unresolved) { print "Warning: program uses non-standard header $_\n" unless ($standard_headers{$_}) or ($param{"STDHDRS"} =~ /$_/); } print "\n"; } # check if we have info for the djgpp output if (!exists $param{"DJGPP_RELEASE_CFLAGS"}) { print "DJGPP_RELEASE_CFLAGS parameter not set: skipping djgpp output files\n"; } elsif (!exists $param{"DJGPP_DEBUG_CFLAGS"}) { print "DJGPP_DEBUG_CFLAGS parameter not set: skipping djgpp output files\n"; } elsif (!exists $param{"DJGPP_RELEASE_LFLAGS"}) { print "DJGPP_RELEASE_LFLAGS parameter not set: skipping djgpp output files\n"; } elsif (!exists $param{"DJGPP_DEBUG_LFLAGS"}) { print "DJGPP_DEBUG_LFLAGS parameter not set: skipping djgpp output files\n"; } else { $got_djgpp = 1; } # check if we have info for the Unix output if (!exists $param{"UNIX_RELEASE_CFLAGS"}) { print "UNIX_RELEASE_CFLAGS parameter not set: skipping Unix output files\n"; } elsif (!exists $param{"UNIX_DEBUG_CFLAGS"}) { print "UNIX_DEBUG_CFLAGS parameter not set: skipping Unix output files\n"; } elsif (!exists $param{"UNIX_RELEASE_LFLAGS"}) { print "UNIX_RELEASE_LFLAGS parameter not set: skipping Unix output files\n"; } elsif (!exists $param{"UNIX_DEBUG_LFLAGS"}) { print "UNIX_DEBUG_LFLAGS parameter not set: skipping Unix output files\n"; } else { $got_unix = 1; } # check if we have info for the Mingw32 output if (!exists $param{"MINGW_RELEASE_CFLAGS"}) { print "MINGW_RELEASE_CFLAGS parameter not set: skipping Mingw32 output files\n"; } elsif (!exists $param{"MINGW_DEBUG_CFLAGS"}) { print "MINGW_DEBUG_CFLAGS parameter not set: skipping Mingw32 output files\n"; } elsif (!exists $param{"MINGW_RELEASE_LFLAGS"}) { print "MINGW_RELEASE_LFLAGS parameter not set: skipping Mingw32 output files\n"; } elsif (!exists $param{"MINGW_DEBUG_LFLAGS"}) { print "MINGW_DEBUG_LFLAGS parameter not set: skipping Mingw32 output files\n"; } else { $got_mingw = 1; } # check if we have info for the Watcom output if (!exists $param{"WATCOM_LFLAGS"}) { print "WATCOM_LFLAGS parameter not set: skipping Watcom output files\n"; } elsif (!exists $param{"WATCOM_CFLAGS"}) { print "WATCOM_CFLAGS parameter not set: skipping Watcom output files\n"; } else { $got_watcom = 1; } # check if we have info for the MSVC output if (!exists $param{"MSVC_RELEASE_LFLAGS"}) { print "MSVC_RELEASE_LFLAGS parameter not set: skipping MSVC output files\n"; } elsif (!exists $param{"MSVC_DEBUG_LFLAGS"}) { print "MSVC_DEBUG_LFLAGS parameter not set: skipping MSVC output files\n"; } elsif (!exists $param{"MSVC_RELEASE_CFLAGS"}) { print "MSVC_RELEASE_CFLAGS parameter not set: skipping MSVC output files\n"; } elsif (!exists $param{"MSVC_DEBUG_CFLAGS"}) { print "MSVC_DEBUG_CFLAGS parameter not set: skipping MSVC output files\n"; } else { $got_msvc = 1; } # check for include directories if (exists $param{"INCDIR"}) { $param{DJGPP_RELEASE_CFLAGS} .= " -I ".$param{"INCDIR"}; $param{DJGPP_DEBUG_CFLAGS} .= " -I ".$param{"INCDIR"}; $param{UNIX_RELEASE_CFLAGS} .= " -I ".$param{"INCDIR"}; $param{UNIX_DEBUG_CFLAGS} .= " -I ".$param{"INCDIR"}; $param{MINGW_RELEASE_CFLAGS} .= " -I ".$param{"INCDIR"}; $param{MINGW_DEBUG_CFLAGS} .= " -I ".$param{"INCDIR"}; $param{MSVC_RELEASE_CFLAGS} .= ' /I "'.$param{"INCDIR"}.'"'; $param{MSVC_DEBUG_CFLAGS} .= ' /I"'.$param{"INCDIR"}.'"'; } # add platform defines $param{DJGPP_RELEASE_CFLAGS} .= " -D TARGET_DJGPP"; $param{DJGPP_DEBUG_CFLAGS} .= " -D TARGET_DJGPP"; $param{UNIX_RELEASE_CFLAGS} .= " -D TARGET_UNIX"; $param{UNIX_DEBUG_CFLAGS} .= " -D TARGET_UNIX"; $param{MINGW_RELEASE_CFLAGS} .= " -D TARGET_MINGW"; $param{MINGW_DEBUG_CFLAGS} .= " -D TARGET_MINGW"; $param{MSVC_RELEASE_CFLAGS} .= " -D TARGET_MSVC"; $param{MSVC_DEBUG_CFLAGS} .= " -D TARGET_MSVC"; # write out GNU makefiles for djgpp, Unix, and Mingw32 if ($got_djgpp or $got_unix or $got_mingw) { print "Writing makefiles...\n "; if ($got_djgpp) { print " makefile.dj"; open FILE, "> $build/makefile.dj" or die "\nError creating makefile.dj:\n $!"; print FILE "# generated by $me: makefile for djgpp\n\n"; print FILE "CC = " . ($cplusplus ? "gxx" : "gcc") . "\n"; print FILE < $build/makefile.uni" or die "\nError creating makefile.uni:\n $!"; print FILE "# generated by $me: makefile for Unix\n\n"; print FILE "CC = " . ($cplusplus ? "g++" : "gcc") . "\n"; print FILE < $build/makefile.mgw" or die "\nError creating makefile.mgw:\n $!"; print FILE "# generated by $me: makefile for Mingw32\n\n"; print FILE "CC = " . ($cplusplus ? "g++" : "gcc") . "\n"; print FILE < $build/makefile.all" or die "\nError creating makefile.all:\n $!"; print FILE < $build/watmake.bat" or die "\nError creating watmake.bat:\n $!"; binmode FILE; print FILE < _ld.arg\r echo name $doslib\\$param{NAME}.exe >> _ld.arg\r EOF while ($param{"WATCOM_LFLAGS"} =~ /"([^"]+)"/g) { print FILE "echo $1 >> _ld.arg\r\n"; } print FILE "\r\n"; for (sort keys %sources) { $filename = $_; $filename =~ s/\//\\/g; $filename =~ /([^\\.]+)\./; $objname = "$dosobj\\$1.obj"; print FILE "echo $filename\r\n"; print FILE "wcl386.exe $param{WATCOM_CFLAGS} -c $filename /fo=$objname\r\n"; print FILE "echo file $objname >> _ld.arg\r\n\r\n"; } print FILE < nul\r \r echo Done!\r EOF close FILE; } if ($got_msvc) { # write a MSVC 6.0 .dsp format project print "Writing $param{NAME}.dsp\n"; open FILE, "> $build/$param{NAME}.dsp" or die "\nError creating $param{NAME}.dsp:\n $!"; binmode FILE; binmode DATA; while () { s/\r//g; chomp; if (/__SOURCES__/) { # write list of source files for (sort keys %sources) { $filename = $_; $filename =~ s/\//\\/g; print FILE "# Begin Source File\r\n\r\nSOURCE=.\\$filename\r\n# End Source File\r\n"; } } elsif (/__HEADERS__/) { # write list of header files for (sort keys %headers) { $filename = $_; $filename =~ s/\//\\/g; print FILE "# Begin Source File\r\n\r\nSOURCE=.\\$filename\r\n# End Source File\r\n"; } } else { # change 'untitled' to our project name s/untitled/$param{"NAME"}/g; # change Intermediate_Dir to our obj directory s/__LIBDIR__/$unixlib/g; # change Output_Dir to our bin directory s/__OBJDIR__/$unixobj/g; # change __RLIBS__ and __DLIBS__ s/__RLIBS__/$param{"MSVC_RELEASE_LFLAGS"}/; s/__DLIBS__/$param{"MSVC_DEBUG_LFLAGS"}/; # change __RFLAGS__ and __DFLAGS__ s/__RFLAGS__/$param{"MSVC_RELEASE_CFLAGS"}/; s/__DFLAGS__/$param{"MSVC_DEBUG_CFLAGS"}/; print FILE "$_\r\n"; } } close FILE; # write a batch file for building with MSVC print "Writing msvcmake.bat\n"; open FILE, "> $build/msvcmake.bat" or die "\nError creating msvcmake.bat:\n $!"; binmode FILE; print FILE <" : ">>") . " _ld.arg\r\n\r\n"; $first = 0; } print FILE < nul\r \r echo Done!\r :end\r EOF close FILE; } # write a 'make clean' batch file print "Writing clean.bat\n"; open FILE, "> $build/clean.bat" or die "\nError creating clean.bat:\n $!"; binmode FILE; print FILE < fixdjgpp.bat" or die "\nError creating fixdjgpp.bat:\n $!"; binmode FILE; print FILE < fixunix.sh" or die "\nError creating fixunix.sh:\n $!"; print FILE < \\\$tmpfile && touch -r {} \\\$tmpfile && mv \\\$tmpfile {}" \\; mkdir lib lib/unix obj obj/unix obj/unix/$param{"NAME"} obj/unix/$param{"NAME"}d echo "Ready for building in Unix -- type:" echo " 'make' or 'make lib' for all builds" echo " 'make debug' for a debugging build" echo " 'make release' for a release build" echo " 'make clean' to tidy up" EOF close FILE; chmod 0755, "fixunix.sh"; } if ($got_mingw) { print " fixmingw.bat"; open FILE, "> fixmingw.bat" or die "\nError creating fixmingw.bat:\n $!"; binmode FILE; print FILE < fixwat.bat" or die "\nError creating fixwat.bat:\n $!"; binmode FILE; print FILE < fixmsvc.bat" or die "\nError creating fixmsvc.bat:\n $!"; binmode FILE; print FILE < # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 # TARGTYPE "Win32 (x86) Static Library" 0x0104 CFG=untitled - Win32 Debug Dynamic !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "untitled.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "untitled.mak" CFG="untitled - Win32 Debug Dynamic" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "untitled - Win32 Release Static" (based on "Win32 (x86) Static Library") !MESSAGE "untitled - Win32 Debug Static" (based on "Win32 (x86) Static Library") !MESSAGE "untitled - Win32 Release Dynamic" (based on "Win32 (x86) Dynamic-Link Library") !MESSAGE "untitled - Win32 Debug Dynamic" (based on "Win32 (x86) Dynamic-Link Library") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe MTL=midl.exe RSC=rc.exe !IF "$(CFG)" == "untitled - Win32 Release Static" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "__LIBDIR__/msvc" # PROP Intermediate_Dir "__OBJDIR__/msvc/untitleds" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_LIB" /c # ADD CPP /nologo __RFLAGS__ /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_LIB" /c # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x809 /d "NDEBUG" # ADD RSC /l 0x809 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LIB32=link.exe -lib # ADD BASE LIB32 /nologo # ADD LIB32 /nologo /out:"lib/msvc/untitleds.lib" !ELSEIF "$(CFG)" == "untitled - Win32 Debug Static" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "__LIBDIR__/msvc" # PROP Intermediate_Dir "__OBJDIR__/msvc/untitledds" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_LIB" /c # ADD CPP /nologo __DFLAGS__ /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_LIB" /c # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x809 /d "_DEBUG" # ADD RSC /l 0x809 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LIB32=link.exe -lib # ADD BASE LIB32 /nologo # ADD LIB32 /nologo /out:"lib/msvc/untitledds.lib" !ELSEIF "$(CFG)" == "untitled - Win32 Release Dynamic" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "__LIBDIR__/msvc" # PROP Intermediate_Dir "__OBJDIR__/msvc/untitled" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" LIB32=link.exe # ADD BASE CPP /nologo /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "untitled_EXPORTS" /c # ADD CPP /nologo __RFLAGS__ /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "untitled_EXPORTS" /c # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x809 /d "NDEBUG" # ADD RSC /l 0x809 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 # ADD LINK32 __RLIBS__ kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"lib/msvc/untitled.dll" # SUBTRACT LINK32 /incremental:yes !ELSEIF "$(CFG)" == "untitled - Win32 Debug Dynamic" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "__LIBDIR__/msvc" # PROP Intermediate_Dir "__OBJDIR__/msvc/untitledd" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" LIB32=link.exe # ADD BASE CPP /nologo /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "untitled_EXPORTS" /c # ADD CPP /nologo __DFLAGS__ /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "untitled_EXPORTS" /c # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x809 /d "_DEBUG" # ADD RSC /l 0x809 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept # ADD LINK32 __DLIBS__ kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"lib/msvc/untitledd.dll" /pdbtype:sept # SUBTRACT LINK32 /incremental:no /nodefaultlib !ENDIF # Begin Target # Name "untitled - Win32 Release Static" # Name "untitled - Win32 Debug Static" # Name "untitled - Win32 Release Dynamic" # Name "untitled - Win32 Debug Dynamic" # Begin Group "Source Files" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" __SOURCES__ # End Group # Begin Group "Header Files" # PROP Default_Filter "h;hpp;hxx;hm;inl" __HEADERS__ # End Group # End Target # End Project