#============================================================================ # Rules for creating msvc projectfiles #============================================================================ # BUGS & TODO #------------ # - Create a secondary target (such as "msvcinst") which copies the generated # project files from the build/"out" directory back into the source # directory. This is useful for maintainers who, after having created and # tested a new set of project files, want to then commit them to the CVS # repository. # # - Either respect ExternaLibs() or fix all the Jamfiles which require special # Windows libraries to invoke MsvcExternalLibrary(). This is necessary for # modules such as cssocket and ensocket which require wsock32.lib, for # instance. There are a number of other such modules. The current monlithic # solution of placing this information in CS/mk/msvcgen/Jamconfig is ugly, # error-prone, and a maintenance headache. # # - Overhaul the "config" file handling rule so that it associates # configuration files with built targets. This will allow the generated # projects to reference configuration files. Rather than the present # InstallConfig rule, we either need a ConfigFile:: rule, or # we should upgrade the Application and Plugin rules to also accept # configuration files. # # - Likewise, provide a generic Resources() rule which allows specification of # additional textual resources for inclusion in generated projects. # # - Upgrade module Jamfiles to mention headers from the CS/include/module # directory. This will allow related headers to appear in the generated # project files. For instance, the libcsengine project should mention # headers from CS/include/csengine, in addition to the ones from # CS/libs/csengine which it currently mentions. # # - When PERL5.SDK.AVAILABLE is "yes", Jam reports that it doesn't know how to # locate or create csperlxs.c. if $(MSVCGEN_CONFIG) { MSVCGEN = "$(PERL) $(TOP)/mk/msvcgen/msvcgen.pl" ; MKVERRES = "$(SHELL) $(TOP)/libs/cssys/win32/mkverres.sh" ; MKMETADATARES = "$(SHELL) $(TOP)/libs/cssys/win32/mkmetadatares.sh" ; MERGERES = "$(SHELL) $(TOP)/libs/cssys/win32/mergeres.sh" ; MSVCGEN_BUILD_ROOT = $(BUILDTOP)/out ; MSVC_VERSION ?= 6 ; if $(MSVC_VERSION) = 6 { MSVCGEN_LOCATE_TARGET ?= $(MSVCGEN_BUILD_ROOT)/mk/visualc6 ; MSVCGEN_LOCATE_FRAGMENT ?= $(MSVCGEN_BUILD_ROOT)/mk/fragment6 ; MSVCGEN_TEMPLATEDIR ?= $(TOP)/mk/msvcgen/template6 ; MSVCGEN_EXTRA_OPTS = ; SSUFPRJ = dsp ; SSUFWSP = dsw ; SUFPRJ = .dsp ; SUFWSP = .dsw ; } else if $(MSVC_VERSION) = 7 { MSVCGEN_LOCATE_TARGET ?= $(MSVCGEN_BUILD_ROOT)/mk/visualc7 ; MSVCGEN_LOCATE_FRAGMENT ?= $(MSVCGEN_BUILD_ROOT)/mk/fragment7 ; MSVCGEN_TEMPLATEDIR ?= $(TOP)/mk/msvcgen/template7 ; MSVCGEN_EXTRA_OPTS = --xml-protect ; SSUFPRJ = vcproj ; SUFPRJ = .vcproj ; SSUFWSP = sln ; SUFWSP = .sln ; } else { EXIT "No support for MSVC version $(MSVC_VERSION) yet!" ; } #---------------------------------------------------------------------------- # Override some rules ## MsvcProject target : sources : type : target-with-ext rule MsvcProject { local rcpath resource msvcname target fragments fragroot files i ; switch $(3) { case appgui : msvcname = app$(<) ; case appcon : msvcname = app$(<) ; case plugin : msvcname = plg$(<) ; case library : msvcname = lib$(<) ; case group : msvcname = grp$(<) ; case * : exit "Unknown msvc projecttype: $(3) specified!" ; } $(<)_MSVCNAME = $(msvcname) ; fragroot = $(MSVCGEN_LOCATE_FRAGMENT)/$(msvcname).frag ; NotFile $(fragroot) ; fragments = [ FAppendSuffix $(msvcname) : .frag.cff ] [ FAppendSuffix $(msvcname) : .frag.dpf ] [ FAppendSuffix $(msvcname) : .frag.pjf ] ; MakeLocate $(fragments) : $(MSVCGEN_LOCATE_FRAGMENT) ; target = [ FAppendSuffix $(msvcname) : $(SUFPRJ) ] ; MakeLocate $(target) : $(MSVCGEN_LOCATE_TARGET) ; target += $(fragments) ; $(<)_TARGET = $(target) ; # Only include source and headers files for now. In the future, we also # want to include .cfg files and any other textual resources which which the # user might care to read/view in the MSVC IDE. for i in $(>) { i = $(i:G=$(LOCATE_SOURCE)) ; switch $(i:S) { case .h : files += $(i) ; case .hpp : files += $(i) ; case .H : files += $(i) ; case .c : files += $(i) ; case .cc : files += $(i) ; case .cpp : files += $(i) ; case .m : files += $(i) ; case .mm : files += $(i) ; case .M : files += $(i) ; } } # Search at the correct place for the files SEARCH on $(files) = $(SEARCH_SOURCE) ; # Add resource file if $(3) = "plugin" || $(3) = "appgui" || $(3) = "appcon" { resource = $(msvcname:S=.rc) ; # @@@ Uber-ugly rcpath = ../../../mk/visualc7/$(msvcname:S=.rc) ; #files += $(resource) ; Depends $(target) : $(resource) ; LOCATE on $(resource) = $(MSVCGEN_LOCATE_TARGET) ; SEARCH on $(resource) = $(MSVCGEN_LOCATE_FRAGMENT) ; NAME on $(resource) = $(<) ; #RCNAME on $(<) = $(resource) ; $(<)_RCNAME = $(resource) ; #ResourceGen $(resource) ; local versionrc = $(resource:S=.vrctmp) ; # 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 $(versionrc) = $(v1) $(v2) $(v3) $(v4) ; # @@@ The "Help" rule is usually invoked after 'Plugin'/'Application', # so "$(<)_help" is empty... DESCRIPTION on $(versionrc) = $($(<)_help) ; LOCATE on $(versionrc) = $(MSVCGEN_LOCATE_FRAGMENT) ; GenerateWin32VersionRc $(versionrc) ; Always $(versionrc) ; Win32Resource $(<) : $(versionrc) ; RmTemps $(target) : $(versionrc) ; if $(3) = "plugin" { local metarc = $(resource:S=.mrctmp) ; LOCATE on $(metarc) = $(MSVCGEN_LOCATE_FRAGMENT) ; SEARCH on $(metarc) = $(SEARCH_SOURCE) ; Depends $(metarc) : $($(<)_METAFILE) ; GenerateWin32MetadataRc $(metarc) : $($(<)_METAFILE) ; Always $(metarc) ; Win32Resource $(<) : $(metarc) ; RmTemps $(target) : $(metarc) ; } Always $(resource) ; } RAWNAME on $(target) = $(<) ; PROJECTNAME on $(target) = $(msvcname) ; TARGET on $(target) = $(4) ; TYPE on $(target) = $(3) ; FRAGMENT_ROOT on $(target) = $(fragroot) ; DEPEND on $(target) += $(MSVC.DEPEND) $(MSVC.DEPEND.$(3)) ; LIBRARIES on $(target) += $(MSVC.LIBRARY) $(MSVC.LIBRARY.$(3)) ; LFLAGS on $(target) += $(MSVC.LFLAGS) $(MSVC.LFLAGS.$(3)) ; CFLAGS on $(target) += $(MSVC.CFLAGS) $(MSVC.CFLAGS.$(3)) ; Depends msvcgen : $(target) ; Depends $(target) : $(files) $(MSVCGEN_LOCATE_FRAGMENT:G=dir) ; MsvcProjectGen $(target) : $(files) $(rcpath) ; Always $(target) ; MSVCWorkspace csall : $(fragments) : $(fragroot) ; Clean msvcclean : $(target) ; } #---------------------------------------------------------------------------- rule Application { # _Options $(<) : $(3) ; local projtype ; if $(CONSOLEAPP_$(<)) = "yes" { projtype = appcon ; } else { projtype = appgui ; } MsvcProject $(<) : $(>) : $(projtype) : $(<:S=.exe) ; CompileGroups $(<) : all apps ; } rule Plugin { local metafile ; metafile = [ FAppendSuffix $(<) : $(SUFMETA) ] ; SEARCH on $(metafile) = $(SEARCH_SOURCE) ; $(<)_METAFILE = $(metafile) ; MsvcProject $(<) : $(>) : plugin : $(<:S=.dll) ; CompileGroups $(<) : all plugins ; } rule Library { MsvcProject $(<) : $(>) : library : $(<:S=.lib) ; CompileGroups $(<) : all libs ; } rule RegisterCompileGroups { local i ; for i in $(<) { RegisterCompileGroup $(i) ; } } rule RegisterCompileGroup { MsvcProject $(<) : $(>) : group ; } rule CompileGroups { for i in $(>) { DEPEND on $($(i)_TARGET) += $($(<)_MSVCNAME) ; } } rule LinkWith { DEPEND on $($(<)_TARGET) += lib$(>) ; } rule MsvcExternalLibrary { LIBRARIES on $($(<)_TARGET) += $(>) ; } rule CFlags { if $(>) != "" { CFLAGS on $($(<)_TARGET) += $(>) ; } } rule LFlags { LFLAGS on $($(<)_TARGET) += $(>) ; } rule ExternalLibs { local i ; for i in $(>) { CFlags $(<) : $($(i).CFLAGS) ; LFlags $(<) : $($(i).LFLAGS) ; MsvcExternalLibrary $(<) : $($(i).MSVCLIBS) ; } } rule MSVCWorkspace { local target ; target = [ FAppendSuffix $(<) : $(SUFWSP) ] ; MakeLocate $(target) : $(MSVCGEN_LOCATE_TARGET) ; Depends msvcgen : $(target) ; Depends $(target) : $(>[1]) ; MsvcWorkspaceGen $(target) : $(3) ; RmTemps $(target) : $(>) ; } rule Win32Resource { Depends $(<) : $($(<)_RCNAME) ; Depends $($(<)_RCNAME) : $(>) ; MergeRcs $($(<)_RCNAME) : $(>) ; } #---------------------------------------------------------------------------- actions MsvcProjectGen { $(MSVCGEN) \ --quiet \ --project \ $(MSVCGEN_EXTRA_OPTS) \ --project-extension=$(SSUFPRJ) \ --name=$(RAWNAME) \ --template=$(TYPE) \ --template-dir=$(MSVCGEN_TEMPLATEDIR) \ --project-name=$(PROJECTNAME) \ --output=$(<[1]) \ --target=$(TARGET) \ --fragment=$(FRAGMENT_ROOT) \ --depend=$(DEPEND) \ --library=$(LIBRARIES) \ --lflags='$(LFLAGS)' \ --cflags='$(CFLAGS)' \ --strip-root='$(TOP)/' \ --strip-root='$(MSVCGEN_BUILD_ROOT)/' \ $(>) } actions together MsvcWorkspaceGen { $(MSVCGEN) \ --quiet \ --workspace \ $(MSVCGEN_EXTRA_OPTS) \ --workspace-extension=$(SSUFWSP) \ --output=$(<) \ --template-dir=$(MSVCGEN_TEMPLATEDIR) \ $(>) } actions together MergeRcs { $(MERGERES) '$(<)' '$(TOP)' '../..' '$(>)' } #---------------------------------------------------------------------------- RegisterCompileGroups all apps plugins libs ; NotFile msvcgen ; Always msvcgen ; Clean clean : $(MSVCGEN_LOCATE_TARGET:G=dir) ; Clean clean : $(MSVCGEN_LOCATE_FRAGMENT:G=dir) ; Clean clean : $(MSVCGEN_BUILD_ROOT) ; Clean msvcclean : $(MSVCGEN_LOCATE_TARGET:G=dir) ; Clean msvcclean : $(MSVCGEN_LOCATE_FRAGMENT:G=dir) ; }