#============================================================================ # Jam configuration and actions for Win32 # Copyright (C)2003 by Matze Braun # Copyright (C)2004 by Eric Sunshine # # This library is free software; you can redistribute it and/or modify it # under the terms of the GNU Library General Public License as published by # the Free Software Foundation; either version 2 of the License, or (at your # option) any later version. # # This library is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public # License for more details. # # You should have received a copy of the GNU Library General Public License # along with this library; if not, write to the Free Software Foundation, # Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # #============================================================================ SHELL ?= "/bin/sh" ; CMD.WINDRES ?= windres ; # DLL-tools not used by this script, but clients might have a need for them. CMD.DLLTOOL ?= dlltool ; CMD.DLLWRAP ?= dllwrap ; USE_DLLWRAP ?= no ; NASM.FLAGS += -f win32 -DEXTERNC_UNDERSCORE ; CCFLAGS += -pipe ; C++FLAGS += -pipe ; LINKLIBS += -L/usr/lib/w32api -lgdi32 -lshell32 ; PLUGIN.LFLAGS += -mwindows ; WINDRES.FLAGS = --use-temp-file ; if "$(USE_DLLWRAP)" = "yes" { PLUGIN.LFLAGS = [ Filter $(PLUGIN.LFLAGS) : -shared ] ; } # Natively-built Jam 2.5 (and probably earlier) on Cygwin fails to perform # library scanning properly and think that all object files need to be rebuilt # (along with everything which depends upon them) when "jam install" follows # "jam all", so disable this feature. if $(OS) = "CYGWIN" { NOARSCAN = true ; } #---------------------------------------------------------------------------- # resource handling # Unfortunately we can't simply specify resources on the source list, because # Mingw/Cygwin have the limitation that they can only link 1 resource file # in. So we have to concatenate all resourcefiles here before compiling them. actions GenerateWin32VersionRc { cat > $(<) << __EOF__ // This file is generated automatically. 1 VERSIONINFO FILEVERSION $(PACKAGE_VERSION_LIST[1]), $(PACKAGE_VERSION_LIST[2]), $(PACKAGE_VERSION_LIST[3]), $(PACKAGE_VERSION_LIST[4]) PRODUCTVERSION $(PACKAGE_VERSION_LIST[1]), $(PACKAGE_VERSION_LIST[2]), $(PACKAGE_VERSION_LIST[3]), $(PACKAGE_VERSION_LIST[4]) #ifdef CS_DEBUG FILEFLAGS 0x1 #else FILEFLAGS 0x0 #endif { BLOCK "StringFileInfo" { BLOCK "040904E4" { VALUE "ProductName", "$(PRODUCT_NAME)" VALUE "ProductVersion", "$(PACKAGE_VERSION)" VALUE "FileVersion", "$(PACKAGE_VERSION)" VALUE "LegalCopyright", "$(PACKAGE_COPYRIGHT)" VALUE "FileDescription", "$(PRODUCT_DESCRIPTION)" #ifdef CS_DEBUG VALUE "Comments", "Debug build" #else VALUE "Comments", "Release build" #endif VALUE "WWW", "$(PACKAGE_HOMEPAGE)" } } } __EOF__ } actions GenerateWin32ManifestRc { cat > $(<) << __EOF__ // This file is generated automatically. 1 24 "$(MANIFEST_NAME)" __EOF__ } actions GenerateWin32Manifest { cat > $(<) << __EOF__ > $(<) cat >> $(<) << __EOF__ processorArchitecture="X86" name="$(PRODUCT_NAME)" type="win32" /> $(PRODUCT_DESCRIPTION) __EOF__ } actions GenerateWin32MetadataRc { cat > $(<) << __EOF__ // This file is automatically generated. 17485 RCDATA { __EOF__ cat $(>) | $(SED) "s:\":\"\":g" | $(SED) "s:\(.*\): \"\1\",:g" >> $(<) cat >> $(<) << __EOF__ "\0" } __EOF__ } actions GenerateIconRc { echo '1 ICON "$(>)"' > $(<) } actions together CompileResources { cat $(>) | $(CMD.WINDRES) $(WINDRES.FLAGS) $(RCFLAGS) --include-dir=$(>:D) -o $(<) } rule CompileResources { Depends $(<) : $(>) ; } ## Win32Resource basename : rcfiles ## Specify .rc files for the target known as basename. The .rc files should ## already have SEARCH set appropriately. rule Win32Resource { local target = $($(<)_TARGET) ; local rcobject = [ DoObjectGrist $(<)_resource.o ] ; LOCATE on $(rcobject) = $(LOCATE_TARGET) ; SEARCH on $(rcobject) = $(LOCATE_TARGET) ; # only add 1 resource object per target if ! $($(<)_HASWIN32RESOURCE) { $(<)_HASWIN32RESOURCE = yes ; ExtraObjects $(<) : $(rcobject) ; } CompileResources $(rcobject) : $(>) ; } ## Win32RcFlags basename : rcfiles ## Specify flags passed to the resource compiler when compiling resources ## for the target known as basename. rule Win32RcFlags { local rcobject = [ DoObjectGrist $(<)_resource.o ] ; RCFLAGS on $(rcobject) += $(>) ; } if $(USE_DLLWRAP) = "yes" { rule GenerateExportDefs { SEARCH on $(<) = $(LOCATE_TARGET) ; MakeLocate $(<) : $(LOCATE_TARGET) ; Depends $(<) : $(>) ; } actions GenerateExportDefs { echo "EXPORTS" > $(<) echo " plugin_compiler" >> $(<) $(SED) '//!d;s:[ ]*\(..*\): \1_scfInitialize:;p;s:_scfInitialize:_scfFinalize:;p;s:_scfFinalize:_Create:' < $(>) >> $(<) } } #---------------------------------------------------------------------------- # linking part ## ConstructApplicationTarget target : options ## Constructs the application target name (ie. foo.exe for foo) rule ConstructApplicationTarget { return $(<).exe ; } rule ConstructStaticLibraryTarget { return lib$(<)$(SUFLIB) ; } rule ConstructSharedLibraryTarget { return $(<)-$(COMPILER.TYPE).dll ; } rule ConstructSharedLibraryLinkLib { return lib$(<)$(SUFLIB) ; } rule ConstructPluginTarget { return $(<).dll ; } # Also invoked by msvcgen.jam. rule MakeVersionRc { # normalize version list local v1, v2, v3, v4 ; v1 = $(PACKAGE_VERSION_LIST[1]) ; if ! $(v1) { v1 = 0 ; } v2 = $(PACKAGE_VERSION_LIST[2]) ; if ! $(v2) { v2 = 0 ; } v3 = $(PACKAGE_VERSION_LIST[3]) ; if ! $(v3) { v3 = 0 ; } v4 = $(PACKAGE_VERSION_LIST[4]) ; if ! $(v4) { v4 = 0 ; } PACKAGE_VERSION_LIST on $(<) = $(v1) $(v2) $(v3) $(v4) ; local desc = [ Description $(>) ] ; if ! $(desc) { desc = "$(>)" ; } PRODUCT_DESCRIPTION on $(<) = $(desc) ; local name ; if $(PACKAGE_LONGNAME) { name = $(PACKAGE_LONGNAME) ; } else if $(PACKAGE_NAME) { name = $(PACKAGE_NAME) ; } else { name = $(>) ; } PRODUCT_NAME on $(<) = $(name) ; GenerateWin32VersionRc $(<) ; } rule MakeManifestFile { # normalize version list local v1, v2, v3, v4 ; v1 = $(PACKAGE_VERSION_LIST[1]) ; if ! $(v1) { v1 = 0 ; } v2 = $(PACKAGE_VERSION_LIST[2]) ; if ! $(v2) { v2 = 0 ; } v3 = $(PACKAGE_VERSION_LIST[3]) ; if ! $(v3) { v3 = 0 ; } v4 = $(PACKAGE_VERSION_LIST[4]) ; if ! $(v4) { v4 = 0 ; } PACKAGE_VERSION_LIST on $(<) = $(v1) $(v2) $(v3) $(v4) ; local desc = [ Description $(>) ] ; if ! $(desc) { desc = "$(>)" ; } PRODUCT_DESCRIPTION on $(<) = $(desc) ; local name ; if $(PACKAGE_NAME) { name = $(PACKAGE_NAME).$(>) ; } else { name = $(>) ; } PRODUCT_NAME on $(<) = $(name) ; GenerateWin32Manifest $(<) ; } rule MakeManifestRc { manifestfile = $(<:S=.manifest) ; MakeLocate $(manifestfile) : [ on $(<) GetVar LOCATE ] ; MakeManifestFile $(manifestfile) : $(>) ; MANIFEST_NAME on $(<) = $(manifestfile:G=) ; GenerateWin32ManifestRc $(<) ; Depends $(<) : $(manifestfile) ; } rule MakeMetadataRc { local metafile = $($(>)_METAFILE) ; local metarc = $(<) ; Depends $(metarc) : $(metafile) ; GenerateWin32MetadataRc $(metarc) : $(metafile) ; Clean $(>)clean : $(metarc) ; Clean clean : $(metarc) ; } rule AppResourceWin32 { local options = $(2) ; local versionrc = [ DoObjectGrist _versionrc.rc ] ; LOCATE on $(versionrc) = $(LOCATE_TARGET) ; SEARCH on $(versionrc) = $(LOCATE_TARGET) ; MakeVersionRc $(versionrc) : $(<) ; Clean $(<)clean : $(versionrc) ; Clean clean : $(versionrc) ; Win32Resource $(<) : $(versionrc) ; if ! [ IsElem nomanifest : $(options) ] { local manifestrc = [ DoObjectGrist _manifestrc.rc ] ; LOCATE on $(manifestrc) = $(LOCATE_TARGET) ; SEARCH on $(manifestrc) = $(LOCATE_TARGET) ; MakeManifestRc $(manifestrc) : $(<) ; Clean $(<)clean : $(manifestrc) ; Clean clean : $(manifestrc) ; Win32Resource $(<) : $(manifestrc) ; } local icon = [ ApplicationIcon win32 : $(<) ] ; if ! $(icon) { local apptype = gui ; if [ IsElem console : $(>) ] { apptype = console ; } icon = [ ApplicationIconDefault win32 : $(apptype) ] ; } if $(icon) { local iconcopy = [ DoObjectGrist $(icon) ] ; MakeLocate $(iconcopy) : $(LOCATE_TARGET) ; Depends $(iconcopy) : $(icon) ; Copy $(iconcopy) : $(icon) ; Clean $(<)clean : $(iconcopy) ; Clean clean : $(iconcopy) ; local iconrc = [ DoObjectGrist $(<)_iconrc.rc ] ; MakeLocate $(iconrc) : $(LOCATE_TARGET) ; Depends $(iconrc) : $(iconcopy) ; GenerateIconRc $(iconrc) : $(iconcopy) ; Clean $(<)clean : $(iconrc) ; Clean clean : $(iconrc) ; Win32Resource $(<) : $(iconrc) ; } } rule PluginResourceWin32 { local versionrc, metarc ; versionrc = [ DoObjectGrist $(<)_versionrc.rc ] ; MakeLocate $(versionrc) : $(LOCATE_TARGET) ; MakeVersionRc $(versionrc) : $(<) ; if $(EMBED_META) = "yes" { metarc = [ DoObjectGrist $(<)_metarc.rc ] ; MakeLocate $(metarc) : $(LOCATE_TARGET) ; MakeMetadataRc $(metarc) : $(<) ; } Clean clean : $(versionrc) $(metarc) ; Clean $(<)clean : $(versionrc) $(metarc) ; Win32Resource $(<) : $(versionrc) $(metarc) ; } # SystemLinkApplication target : objects : options rule SystemLinkApplication { local target = $($(<)_TARGET) ; Depends $(target) : $(>) ; LinkApplication $(target) : $(>) ; # setup clean rules Clean clean : $(target) ; Clean $(<)clean : $(target) ; AppResourceWin32 $(<) : $(3) ; } rule SystemInstallApplication { Depends install_bin : [ DoInstall $(<) : $(bindir) $(2) : $(INSTALL_PROGRAM) ] ; } rule SystemInstallPlugin { Depends install_plugin : [ DoInstall $(<) : $(plugindir) $(2) : $(INSTALL_PROGRAM) ] ; } # SystemLinkPlugin target : objects : options rule SystemLinkPlugin { local target = $($(<)_TARGET) ; if $(USE_DLLWRAP) = "yes" { local exportdefs = [ DoObjectGrist $(<).def ] ; NAME on $(exportdefs) = $(<) ; GenerateExportDefs $(exportdefs) : $($(<)_METAFILE) ; Depends $(target) : $(exportdefs) ; EXPORTDEFS on $(target) = $(exportdefs) ; } Depends $(target) : $(>) ; LinkPlugin $(target) : $(>) ; PluginResourceWin32 $(<) ; if $(EMBED_META) != "yes" { PluginMetaData $(<) : $($(<)_METAFILE) : $(3) ; } Clean clean : $(target) ; Clean $(<)clean : $(target) ; } rule MakeDllDefFile { local def = $(<) ; local objects = $(>) ; MakeLocate $(def) : $(LOCATE.OBJECTS)/libs ; WriteDefHeader $(def) ; for i in $(objects) { local drectve = $(i).drectve ; MakeLocate $(drectve) : [ on $(i) GetVar LOCATE ] ; Depends $(drectve) : $(i) ; Depends $(def) : $(drectve) ; ExtractDrectve $(drectve) : $(i) ; DrectveToDef $(def) : $(drectve) ; Clean clean : $(drectve) ; Clean $(def)clean : $(drectve) ; } } rule SystemLinkSharedLibrary { LFlags $(<) : $(LINKLIBS) ; # The "crystalspace" library is so massive that it blows Jam's command line # length limit when all object files are passed in at once to some command. # However, a DLL, like an executable, needs to be built with all objects at # once. # Problem is, since dllwrap etc. don't support response files, there is no # way to pass all objects at once to it. But, a static library can be built # piecemeal, so we take the detour of creating a static library out of the # DLL objects first. # However, another bug hits us: on MinGW, symbols exported from objects in # static libraries are not automatically exported from the DLL. # We work this around by constructing a .DEF file with all exports of the # DLL. Conveniently (somewhat), all exported symbols are into a section # ".drectve" of an object file by gcc. After extracting these sections and # some postprocessing, we finally have all .DEF entries. Phew. local lib = $(<).a ; MakeLocate $(lib) $(lib)($(>:BS)) : $(LOCATE.OBJECTS)/libs ; Depends $(lib) : $(lib)($(>:BS)) ; local i ; for i in $(>) { Depends $(lib)($(i:BS)) : $(i) ; } Archive $(lib) : $(>) ; Ranlib $(lib) ; #RmTemps $(lib) : $(>) ; Depends $(<) : $(lib) ; local def = $(<).def ; MakeDllDefFile $(def) : $(>) ; Depends $(<) : $(def) ; Clean clean : $(def) ; Clean $(<)clean : $(def) ; Depends $(<)clean : $(def)clean ; EXPORTDEFS on $(<) = $(def) ; IMPLIB on $(<) = $(3) ; Depends $(3) : $(<) ; LinkSharedLibrary $(<) : $(lib) ; Clean clean : $(target) ; Clean $(<)clean : $(target) ; } actions ExtractDrectve { $(CMD.OBJCOPY) -j .drectve -O binary $(>) $(<).tmp echo >> $(<).tmp # Cheap trick to ensure there's always a .tmp file; # the action should not break with no .drectve - no exports # is a valid scenario. $(CMD.STRINGS) -n 1 $(<).tmp > $(<) # Run strings since the section data may be # padded with zeroes, get rid of those. rm $(<).tmp } actions WriteDefHeader { echo "EXPORTS" > $(<) } actions piecemeal together DrectveToDef { for d in $(>) do sed -e "s/ /\\ /g" $d | sed -e "s/-export:\(.*\)/\1/g" | sed -e "s/,data/ DATA/g" >> $(<) done } actions GenerateImportLib { $(CMD.DLLTOOL) -d $(>) -l $(<) } actions LinkApplication bind NEEDLIBS bind EXTRAOBJECTS { $(CMD.LINK) -o $(<) $(>) $(EXTRAOBJECTS) $(NEEDLIBS) $(LINKLIBS) } if $(USE_DLLWRAP) != "yes" { actions LinkPlugin bind NEEDLIBS bind EXTRAOBJECTS { $(CMD.LINK) -o $(<) $(>) $(EXTRAOBJECTS) $(NEEDLIBS) $(LINKLIBS) } } else { actions LinkPlugin bind NEEDLIBS bind EXTRAOBJECTS bind EXPORTDEFS { $(CMD.DLLWRAP) --driver-name=$(CMD.LINK) --dllname $(<:B) --def=$(EXPORTDEFS) -o $(<) $(>) $(EXTRAOBJECTS) $(NEEDLIBS) $(LINKLIBS) } } actions LinkSharedLibrary bind NEEDLIBS bind EXTRAOBJECTS bind EXPORTDEFS bind IMPLIB { $(CMD.DLLWRAP) --driver-name=$(CMD.LINK) --dllname $(<:B).dll --def=$(EXPORTDEFS) --implib $(IMPLIB) -o $(<) $(>) $(EXTRAOBJECTS) $(NEEDLIBS) $(LINKLIBS) touch $(IMPLIB) # ensure the IMPLIB is always newer than the DLL, # since the IMPLIB depends on the DLL. }