#============================================================================ # Utility rules for static builds without plugins # Copyright (C)2003 by Matze Braun # # 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. # #============================================================================ # all private rule GenerateStaticPluginBoilerplate { ResponseFile $(<) : "// This file is automatically generated." "#include \"cssysdef.h\"" "#include \"csutil/scf.h\"" "" "// Put static linking stuff into own section." "// The idea is that this allows the section to be swapped out but not" "// swapped in again b/c something else in it was needed." "#if !defined(CS_DEBUG) && defined(CS_COMPILER_MSVC)" "#pragma const_seg(\".CSmetai\")" "#pragma comment(linker, \"/section:.CSmetai,r\")" "#pragma code_seg(\".CSmeta\")" "#pragma comment(linker, \"/section:.CSmeta,er\")" "#pragma comment(linker, \"/merge:.CSmetai=.CSmeta\")" "#endif" : notfile ; } rule GenerateStaticPluginInstantiation { GenerateStaticPluginBoilerplate $(<) ; ResponseFile $(<) : "SCF_USE_STATIC_PLUGIN($(>:B))" : notfile ; } rule GenerateStaticPluginRegistration { GenerateStaticPluginBoilerplate $(<) ; GenerateStaticPluginRegistration1 $(<) : $(>) ; } rule BuildStaticRegFile { local statictarget = $(>) ; # prepare source files local sources = [ DoObjectGrist _$(<)_static_reg.cpp ] ; local object = [ CompileObject $(sources) ] ; MakeLocate $(sources) : $(LOCATE_TARGET) ; MakeLocate $(object) : $(LOCATE_TARGET) ; local metalist metafile i ; for i in $(<) { metafile = $($(i)_METAFILE) ; metalist += $(metafile) ; Depends $(sources) : $(metafile) ; } GenerateStaticPluginRegistration $(sources) : $(metalist) ; Clean $(statictarget)clean : $(sources) ; Clean $(statictarget)clean : $(object) ; return $(object) ; } rule BuildStaticUseFile { local statictarget = $(2) ; local package = $(3) ; # prepare source files local sources ; if $(3) { sources = [ DoObjectGrist _cs_static_use_$(package).cpp ] ; } else { sources = [ DoObjectGrist _cs_static_use.cpp ] ; } local object = [ CompileObject $(sources) ] ; MakeLocate $(sources) : $(LOCATE_TARGET) ; SEARCH on $(sources) = $(LOCATE_TARGET) ; MakeLocate $(object) : $(LOCATE_TARGET) ; C++FLAGS on $(object) += $($($(>).EXTERNALLIBS).CFLAGS) ; GenerateStaticPluginInstantiation $(sources) : $(<) ; Clean $(statictarget)clean : $(sources) ; Clean $(statictarget)clean : $(object) ; return $(object) ; } ## LinkStaticPlugins target : plugins [: optionalplugins] [: package] ## Builds the plugins in 'plugins' (and 'optionalplugins') statically into ## 'target'. Can be used both for static plugins from the local project or ## an external project. In the latter case, the project's static plugin ## library has to have been built, also, the ".STATICDEPS" ## variable must contain a path to a specially generated Jamfile that ## contains information about the plugins provided by as well as external ## dependencies. The static plugins library for both local and external ## package must be explicitly linked into 'target'. rule LinkStaticPlugins { local package target plugins optplugins ; # Fetch the parameters target = $(1) ; plugins = $(2) ; optplugins = $(3) ; package = $(4) ; if $(package) { # External static plugins. # First include static plugin info if ! $(HAVE_STATICDEPS.$(package)) { include $($(package).STATICDEPS) ; HAVE_STATICDEPS.$(package) = yes ; } local lflags p ; # Collect optional plugins for p in $(optplugins) { if [ IsElem $(p) : $(STATICPLUGINS.AVAILABLE) ] { plugins += $(p) ; } } # Grab flags for p in $(plugins) { NotFile $(p) ; CFlags $(target) : $(STATICPLUGIN.$(p).CFLAGS) ; lflags = [ MergeLFlags $(lflags) : $(STATICPLUGIN.$(p).LFLAGS) ] ; } LFlags $(target) : $(lflags) ; } else { # Local static plugins local lflags libs p ; # Collect optional plugins for p in $(optplugins) { if $($(p)_TARGET) { plugins += $(p) ; } } # Grab flags for p in $(plugins) { lflags += [ Filter $($(p).LFLAGS) : $(LINKLIBS) $(PLUGIN.LFLAGS) ] ; libs += $($(p).NEEDLIBS) ; } LFlags $(target) : [ Reverse [ RemoveDups [ Reverse $(lflags) ] ] ] ; LinkWith $(target) : [ Reverse [ RemoveDups [ Reverse $(libs) ] ] ] ; } # construct initialization sourcefile local staticobject = [ BuildStaticUseFile $(plugins) : $(target) : $(package) ] ; ExtraObjects $(target) : $(staticobject) : inheritcflags ; } ## StaticPluginLibrary name [: rejects] ## Create a library that monolithically contains statically linkable ## versions of all plugins, and also provides a target to install this ## library ("install_staticplugins") as well as resources to facilitate the ## use of that library from external projects. Also, most plugins will ## probably themselves depend on other libraries; while those are correctly ## linked in with the static plugins, they are not built or installed when ## the static plugin library is. ## This library is intended to be used together with the ## "LinkStaticPlugins" rule. rule StaticPluginLibrary { local name = $(<) ; local rejects = $(>) ; local t ; local targets = $(STATICPLUGINS.SUBTARGETS) ; if $(rejects) { targets = [ Filter $(targets) : $(rejects) ] ; } local objects ; for t in $(targets) { objects += $(STATICPLUGINS.OBJECTS.$(t)) ; } # Set up library Library $(name) : $(objects) : noinstall notest independent nohelp ; SEARCH on $(name) += $(LOCATE_TARGET) ; MsvcDefine $(name) : $(STATICPLUGINS.MSVC_DEFINES) ; CFlags $(name) : [ FDefines CS_STATIC_LINKED ] : nostatic ; # Copy a variety of flags local o ; for o in $(objects) { local sourceobj = $(STATICPLUGINS.OBJECTS.$(o)) ; if $(sourceobj) { CCFLAGS on $(o) += [ on $(sourceobj) GetVar CCFLAGS ] ; C++FLAGS on $(o) += [ on $(sourceobj) GetVar C++FLAGS ] ; } } # Write out needed CFLAGS, LFLAGS STATICPLUGINS.DEPENDENCIES = $(name).jam ; MakeLocate $(STATICPLUGINS.DEPENDENCIES) : $(LOCATE.OBJECTS)/libs ; for t in $(targets) { WriteDependencies $(STATICPLUGINS.DEPENDENCIES) : $(t) : $(name) ; } Depends $(name) : $(STATICPLUGINS.DEPENDENCIES) ; Clean $(name)clean : $(STATICPLUGINS.DEPENDENCIES) ; # Install targets Depends install_staticplugins : [ DoInstall [ ConstructLibraryTarget $(name) ] : $(libdir) ] ; Depends install_staticplugins : $(STATICPLUGINS.DEPENDENCIES) ; Depends install_staticplugins : [ DoInstall $(STATICPLUGINS.DEPENDENCIES) : $(libdir) ] ; Depends install_staticplugins : install_libs ; INSTALLEDLIBS_OPTIONAL += $(name) ; # Collect library dependencies. The idea is to built all libs needed by the # static plugins when "jam staticplugins" is invoked. for t in $(targets) { local deplibs ; if $($(t).NEEDLIBS) { deplibs += $($(t).NEEDLIBS) ; } deplibs = [ RemoveDups $(deplibs) ] ; Depends staticplugins : $(deplibs) ; } Help staticplugins : "Build the library with static versions of all plugins" ; Depends staticplugins : libs $(name) ; } #---------------------------------------------------------------------------- # Write out CFLAGS, LFLAGS needed by a plugin rule WriteDependencies { local cflags ; local lflags ; local depfile = $(<) ; local plugin = $(>) ; local name = $(3) ; local depfile_gristed = $(depfile:G=$(plugin)) ; MakeLocate $(depfile_gristed) : [ on $(depfile) GetVar LOCATE ] ; # Collect flags lflags += -l$(name) ; local libs = [ ResolveLibs $($(plugin).NEEDLIBS) ] ; lflags += -l$(libs) ; local l ; for l in $($(plugin).EXTERNALLIBS) { cflags += $($(l).CFLAGS) ; lflags += [ Filter $($(l).LFLAGS) : $(LINKLIBS) $(PLUGIN.LFLAGS) ] ; } lflags += [ Filter $($(plugin).LFLAGS) : $(LINKLIBS) $(PLUGIN.LFLAGS) ] ; CFLAGS on $(depfile_gristed) = "$(cflags)" ; LFLAGS on $(depfile_gristed) = "$(lflags)" ; if $($(depfile).FIRSTTIME) != "yes" { WriteDepFlags1 $(depfile_gristed) : $(plugin) ; $(depfile).FIRSTTIME = "yes" ; } else { WriteDepFlags2 $(depfile_gristed) : $(plugin) ; } Depends $(depfile) : $(depfile_gristed) ; } actions WriteDepFlags1 { cat << EOT > $(<) STATICPLUGINS.AVAILABLE += $(>) ; STATICPLUGIN.$(>).CFLAGS = $(CFLAGS) ; STATICPLUGIN.$(>).LFLAGS = $(LFLAGS) ; EOT } actions WriteDepFlags2 { cat << EOT >> $(<) STATICPLUGINS.AVAILABLE += $(>) ; STATICPLUGIN.$(>).CFLAGS = $(CFLAGS) ; STATICPLUGIN.$(>).LFLAGS = $(LFLAGS) ; EOT } actions piecemeal GenerateStaticPluginRegistration1 { echo 'namespace csStaticPluginInit' >> $(<) echo '{' >> $(<) for x in $(>) do n=`basename $x $(SUFMETA)` echo "static char const metainfo_${n}[] =" >> $(<) $(SED) 's:\\:\\\\:g;s:":\\":g;s:\(.*\):"\1":' < $x >>$(<) echo ";" >> $(<) $(SED) '//!d;s:[ ]*\(..*\): #ifndef \1_FACTORY_REGISTER_DEFINED \ #define \1_FACTORY_REGISTER_DEFINED \ SCF_DEFINE_FACTORY_FUNC_REGISTRATION(\1) \ #endif:g' < $x >> $(<) done echo '' >> $(<) for x in $(>) do n=`basename $x $(SUFMETA)` echo "class ${n}" >> $(<) echo "{" >> $(<) echo "SCF_REGISTER_STATIC_LIBRARY($n,metainfo_${n})" >>$(<) $(SED) '//!d;s:[ ]*\(..*\): #ifndef \1_FACTORY_REGISTERED \ #define \1_FACTORY_REGISTERED \ \1_StaticInit \1_static_init__; \ #endif:g' < $x >> $(<) echo "public:" >> $(<) echo " ${n}();" >> $(<) echo "};" >> $(<) echo "$n::$n() {}" >> $(<) echo "" >> $(<) done echo '}' >> $(<) }