Doubled up variable substitutions in msvc action
"Chambers, Matthew via Boost-build" <[email protected]> Wed, 24 Jun 2020 13:16:32 -0400
| Newsgroups | gmane.comp.lib.boost.build |
|---|---|
| Message-ID | <[email protected]> |
This is a multi-part message in MIME format.
--===============5245480630400970436==
Content-Type: multipart/alternative;
boundary="------------21CA42BC0987BD6EF846758C"
Content-Language: en-US
This is a multi-part message in MIME format.
--------------21CA42BC0987BD6EF846758C
Content-Type: text/plain; charset=utf-8; format=flowed
Content-Transfer-Encoding: 8bit
I have hit an intermittent (hard to reproduce) issue when building a particular target with MSVC. I've added custom versions of msvc.link
and msvc.compile for /clr and .NET support. They've been working fine for the few targets I originally developed them for. This problem
started happening when I recently added another target using these custom versions. The symptom is that I get this link command with doubled
up "link" and flags suggesting the $(.LD) and $(LINKFLAGS) variables are getting doubled up. It's so hard to reproduce I haven't managed to
get any --debug-configuration output when it happens. I've only gotten it to happen on our AWS build agents. I was hoping one of the
veterans would have a hunch about what's happening just from the symptom.
link link /NOLOGO /NOLOGO /INCREMENTAL:NO /INCREMENTAL:NO /DLL /DEBUG /DEBUG /MACHINE:X64 /MACHINE:X64 /MANIFEST /MANIFEST
/subsystem:console /subsystem:console /out:"Z:\path\to\PrmPasefScheduler.dll" /LIBPATH:"Z:\some\path\x64" /LIBPATH:"Z:\some\other\path\x64"
/MACHINE:x64 /FIXED:No /MACHINE:x64 /FIXED:No @"Z:\path\to\PrmPasefScheduler.dll.rsp"
Just in case you want to dig deeper, here is the problematic target:
rule msvc-requirement ( properties * )
{
if ! <toolset>msvc in $(properties) { return <build>no ; }
}
obj PrmScheduler : PrmScheduler.cpp : <conditional>@msvc-requirement <define>UNICODE <define>_UNICODE
<toolset>msvc:<using-clr>true ;
rule prmscheduler-requirements ( properties * )
{
if <address-model>64 in $(properties)
{
return <search>x64 ;
}
else
{
return <search>x86 ;
}
}
rule prmscheduler-usage-requirements ( properties * )
{
if <address-model>64 in $(properties)
{
return <assembly-dependency>$(PRMSCHEDULER_CLI_ROOT)/x64/prmscheduler.dll ;
}
else
{
return <assembly-dependency>$(PRMSCHEDULER_CLI_ROOT)/x86/prmscheduler.dll ;
}
}
searched-lib prmscheduler : : <conditional>@prmscheduler-requirements : : <conditional>@prmscheduler-usage-requirements ;
constant PLATFORM : "x64" ;
lib PrmPasefScheduler
: # sources
PrmScheduler
: # requirements
<library>prmscheduler
<link>shared
<library>$(PWIZ_ROOT_PATH)/pwiz/utility/misc//pwiz_utility_misc/<link>static/<using-clr>false
<linkflags>"/MACHINE:$(PLATFORM) /FIXED:No"
<cxxflags>/permissive
<conditional>@msvc-requirement
<define>UNICODE
<define>_UNICODE
<toolset>msvc:<using-clr>true
: # default-build
: # usage-requirements
<library>prmscheduler
<library>$(PWIZ_ROOT_PATH)/pwiz/utility/misc//pwiz_utility_misc/<link>static/<using-clr>false
;
_
__Here are the custom rules/actions:_
actions compile-c++clr
{
$(.SETUP) $(.CC) @"@($(<[1]:W).rsp:E="$(>[1]:W)" -Fo"$(<[1]:W)" -Yu"$(>[3]:D=)" -Fp"$(>[2]:W)" /clr $(ASSEMBLY_INCLUDE_PATHS)
$(ASSEMBLIES) $(CC_RSPLINE))" $(.CC.FILTER)" > "$(<[1]:W).out"
set status=%ERRORLEVEL%
findstr /V /X "$(>[1]:D=)" "$(<[1]:W).out"
exit %status%
}
rule compile.c++clr ( targets + : sources * : properties * )
{
set-setup-command $(targets) : $(properties) ;
set-assemblies $(<[1]) : $(properties) ;
get-rspline $(targets) : -TP ;
compile-c++clr $(<) : $(>) [ on $(<) return $(PCH_FILE) ] [ on $(<) return $(PCH_HEADER) ] ;
}
actions link.clr.dll bind DEF_FILE LIBRARIES_MENTIONED_BY_FILE
{
$(.SETUP) $(.LD) /DLL $(LINKFLAGS) /out:"$(<[1]:W)" /LIBPATH:"$(LINKPATH:W)" /def:"$(DEF_FILE)" $(OPTIONS)
@"@($(<[1]:W).rsp:E=$(.nl)"$(>)" $(.nl)$(LIBRARIES_MENTIONED_BY_FILE) $(.nl)$(LIBRARIES) $(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_ST).lib"
$(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_SA).lib")" $(MANIFEST_DEPENDENCIES)
if %ERRORLEVEL% NEQ 0 EXIT %ERRORLEVEL%
}
rule link.clr.dll ( targets + : sources * : properties * )
{
set-setup-command $(targets) : $(properties) ;
set-manifest-dependencies $(<[1]) : $(properties) ;
DEPENDS $(<) : [ on $(<) return $(DEF_FILE) ] ;
if <embed-manifest>on in $(properties)
{
msvc.manifest.dll $(targets) : $(sources) : $(properties) ;
}
copy-assemblies $(<[1]) : $(properties) ;
}
_
__Here are the custom features:_
feature.feature assembly : : free dependency ;
feature.feature assembly-dependency : : free dependency ;
feature.feature assembly-dependency-ex : : free ;
feature.feature manifest-dependency : : free dependency ;
feature.feature configuration-file : : free dependency ;
feature.feature using-clr : false true : composite ;
feature.compose <using-clr>true : <asynch-exceptions>on <runtime-link>shared ;
generators.register [ new msvc-linking-generator msvc.link.clr.dll : OBJ SEARCHED_LIB STATIC_LIB : SHARED_LIB : <toolset>msvc
<using-clr>true ] ;
generators.override msvc.link.clr.dll : msvc.link.dll ;
generators.register-c-compiler msvc.compile.c++clr : CPP : OBJ : <toolset>msvc <using-clr>true ;
_
__Here are some utility functions used in the above actions:_
#
# Add /FU and /AI flags for targets using /clr
#
rule set-assemblies ( target : properties * )
{
local assemblies-string ;
local assemblies = [ feature.get-values <assembly> : $(properties) ] ;
if $(assemblies)
{
for local assembly in $(assemblies)
{
local assembly-path = [ $(assembly).name ] ;
if $(assembly-path:S) != ".pdb"
{
if ! [ path.is-rooted $(assembly-path) ]
{
assembly-path = [ path.join [ $(assembly).path ] $(assembly-path:D=) ] ;
}
assembly-path = [ path.native $(assembly-path) ] ;
assemblies-string += " /FU\"$(assembly-path)\"" ;
}
}
}
ASSEMBLIES on $(target) = $(assemblies-string) ;
# add /AI flags for each assembly-dependency's (unique) directory
local assembly-include-string ;
local assembly-dependencies = [ feature.get-values <assembly-dependency> : $(properties) ] ;
if $(assembly-dependencies)
{
local assembly-include-paths ;
for local dependency in $(assembly-dependencies)
{
local dependency-path = [ $(dependency).name ] ;
if ! [ path.is-rooted $(dependency-path) ]
{
dependency-path = [ path.join [ $(dependency).path ] $(dependency-path:D=) ] ;
}
dependency-path = [ path.native $(dependency-path) ] ;
dependency-path = $(dependency-path:D) ;
if ! $(dependency-path) in $(assembly-include-paths)
{
assembly-include-paths += $(dependency-path) ;
assembly-include-string += " /AI\"$(dependency-path)\"" ;
}
}
}
ASSEMBLY_INCLUDE_PATHS on $(target) = $(assembly-include-string) ;
}
#
# Add /MANIFESTDEPENDENCY flags (primarily for side-by-side loading of COM DLLs)
#
local rule set-manifest-dependencies ( target : properties * )
{
local manifest-dependencies-string ;
local manifest-dependencies = [ feature.get-values <manifest-dependency> : $(properties) ] ;
if $(manifest-dependencies)
{
# type='win32' name='<assembly_basename>' version='<assembly_version>'
for local dependency in $(manifest-dependencies)
{
local dependency-path = [ path.native [ $(dependency).name ] ] ;
local dependency-version = [ MATCH "FileVersion: ([0-9\\.]+)" : [ SHELL "ShowVer.exe $(dependency-path)" ] ] ;
# unknown version will cause a runtime-error; is there a better solution?
dependency-version ?= "unknown" ;
# the name of the manifest can not match the basename of the DLL because of a Windows XP loader bug
manifest-dependencies-string += " /MANIFESTDEPENDENCY:\"type='win32' name='$(dependency-path:B).SxS'
version='$(dependency-version)'\"" ;
}
}
MANIFEST_DEPENDENCIES on $(target) = $(manifest-dependencies-string) ;
}
#
# Copy .NET assemblies and their native DLL dependencies to the target's directory;
# Also .NET applications may need a side-by-side configuration file that must be named like $(target).exe.config - copy that if necessary
#
rule copy-assemblies ( target : properties * )
{
local assemblies = [ feature.get-values <assembly> : $(properties) ] ;
assemblies += [ feature.get-values <assembly-dependency> : $(properties) ] ;
if $(assemblies)
{
local target-path = [ on $(target) return $(LOCATE) ] ;
for local assembly in $(assemblies)
{
local assembly-path = [ $(assembly).name ] ;
if ! [ path.is-rooted $(assembly-path) ]
{
assembly-path = [ path.join [ $(assembly).path ] $(assembly-path:D=) ] ;
}
assembly-path = [ path.native $(assembly-path) ] ;
local assembly-at-target-filepath = [ path.native [ path.join $(target-path) $(assembly-path:D=) ] ] ;
if $(assembly-at-target-filepath:L) != $(assembly-path:L) &&
! ( $(assembly-at-target-filepath:L) in $(.unique-targets) )
{
.unique-targets += $(assembly-at-target-filepath:L) ;
if ! [ CHECK_IF_FILE $(assembly-at-target-filepath:L) ]
{
common.hard-link $(assembly-at-target-filepath) : $(assembly-path) ;
DEPENDS $(assembly-at-target-filepath) : $(target-path) [ $(assembly).actualize ] ;
DEPENDS $(target) : $(assembly-at-target-filepath) ;
#JAM_SEMAPHORE on $(target-filepath) = "dotNetSemaphore" ;
#JAM_SEMAPHORE on $(target) = "dotNetSemaphore" ;
}
}
}
}
# .NET applications may need a side-by-side configuration file that must be named like $(target).exe.config
local configuration-file = [ feature.get-values <configuration-file> : $(properties) ] ;
if $(configuration-file)
{
local target-path = [ on $(target) return $(LOCATE) ] ;
local configuration-file-path = [ $(configuration-file).name ] ;
if ! [ path.is-rooted $(configuration-file-path) ]
{
configuration-file-path = [ path.join [ $(configuration-file).path ] $(configuration-file-path:D=) ] ;
}
configuration-file-path = [ path.native $(configuration-file-path) ] ;
local target-filepath = [ path.native [ path.join $(target-path) $(configuration-file-path:D=) ] ] ;
if $(target-filepath) != $(configuration-file-path) &&
! ( $(configuration-file-path) in $(.unique-targets) )
{
.unique-targets += $(configuration-file-path) ;
common.hard-link $(target-filepath) : $(configuration-file-path) ;
DEPENDS $(target-filepath) : $(target-path) ;
DEPENDS $(target) : $(target-filepath) ;
#JAM_SEMAPHORE on $(target-filepath) = "dotNetSemaphore" ;
#JAM_SEMAPHORE on $(target) = "dotNetSemaphore" ;
}
}
}
--------------21CA42BC0987BD6EF846758C
Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: 8bit
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body>
I have hit an intermittent (hard to reproduce) issue when building a
particular target with MSVC. I've added custom versions of msvc.link
and msvc.compile for /clr and .NET support. They've been working
fine for the few targets I originally developed them for. This
problem started happening when I recently added another target using
these custom versions. The symptom is that I get this link command
with doubled up "link" and flags suggesting the $(.LD) and
$(LINKFLAGS) variables are getting doubled up. It's so hard to
reproduce I haven't managed to get any --debug-configuration output
when it happens. I've only gotten it to happen on our AWS build
agents. I was hoping one of the veterans would have a hunch about
what's happening just from the symptom.<br>
<br>
link link /NOLOGO /NOLOGO /INCREMENTAL:NO /INCREMENTAL:NO /DLL
/DEBUG /DEBUG /MACHINE:X64 /MACHINE:X64 /MANIFEST /MANIFEST
/subsystem:console /subsystem:console
/out:"Z:\path\to\PrmPasefScheduler.dll" /LIBPATH:"Z:\some\path\x64"
/LIBPATH:"Z:\some\other\path\x64" /MACHINE:x64 /FIXED:No
/MACHINE:x64 /FIXED:No @"Z:\path\to\PrmPasefScheduler.dll.rsp" <br>
<br>
Just in case you want to dig deeper, here is the problematic target:<br>
<tt><br>
</tt><tt>rule msvc-requirement ( properties * )</tt><tt><br>
</tt><tt>{</tt><tt><br>
</tt><tt> if ! <toolset>msvc in $(properties) { return
<build>no ; }</tt><tt><br>
</tt><tt>}</tt><tt><br>
</tt><tt>obj PrmScheduler : PrmScheduler.cpp :
<conditional>@msvc-requirement <define>UNICODE
<define>_UNICODE <toolset>msvc:<using-clr>true ;</tt><tt><br>
</tt><tt><br>
</tt><tt>rule prmscheduler-requirements ( properties * )</tt><tt><br>
</tt><tt>{</tt><tt><br>
</tt><tt> if <address-model>64 in $(properties)</tt><tt><br>
</tt><tt> {</tt><tt><br>
</tt><tt> return <search>x64 ;</tt><tt><br>
</tt><tt> }</tt><tt><br>
</tt><tt> else</tt><tt><br>
</tt><tt> {</tt><tt><br>
</tt><tt> return <search>x86 ;</tt><tt><br>
</tt><tt> }</tt><tt><br>
</tt><tt>}</tt><tt><br>
</tt><tt><br>
</tt><tt>rule prmscheduler-usage-requirements ( properties * )</tt><tt><br>
</tt><tt>{</tt><tt><br>
</tt><tt> if <address-model>64 in $(properties)</tt><tt><br>
</tt><tt> {</tt><tt><br>
</tt><tt> return
<assembly-dependency>$(PRMSCHEDULER_CLI_ROOT)/x64/prmscheduler.dll
;</tt><tt><br>
</tt><tt> }</tt><tt><br>
</tt><tt> else</tt><tt><br>
</tt><tt> {</tt><tt><br>
</tt><tt> return
<assembly-dependency>$(PRMSCHEDULER_CLI_ROOT)/x86/prmscheduler.dll
;</tt><tt><br>
</tt><tt> }</tt><tt><br>
</tt><tt>}</tt><tt><br>
</tt><tt><br>
</tt><tt>searched-lib prmscheduler : :
<conditional>@prmscheduler-requirements : :
<conditional>@prmscheduler-usage-requirements ;</tt><tt><br>
</tt><tt><br>
</tt><tt>constant PLATFORM : "x64" ;</tt><tt><br>
</tt><tt>lib PrmPasefScheduler</tt><tt><br>
</tt><tt> : # sources</tt><tt><br>
</tt><tt> PrmScheduler</tt><tt><br>
</tt><tt> : # requirements</tt><tt><br>
</tt><tt> <library>prmscheduler</tt><tt><br>
</tt><tt> <link>shared</tt><tt><br>
</tt><tt>
<library>$(PWIZ_ROOT_PATH)/pwiz/utility/misc//pwiz_utility_misc/<link>static/<using-clr>false</tt><tt><br>
</tt><tt> <linkflags>"/MACHINE:$(PLATFORM) /FIXED:No"</tt><tt><br>
</tt><tt> <cxxflags>/permissive</tt><tt><br>
</tt><tt> <conditional>@msvc-requirement</tt><tt><br>
</tt><tt> <define>UNICODE</tt><tt><br>
</tt><tt> <define>_UNICODE</tt><tt><br>
</tt><tt> <toolset>msvc:<using-clr>true</tt><tt><br>
</tt><tt> : # default-build</tt><tt><br>
</tt><tt> : # usage-requirements</tt><tt><br>
</tt><tt> <library>prmscheduler</tt><tt><br>
</tt><tt>
<library>$(PWIZ_ROOT_PATH)/pwiz/utility/misc//pwiz_utility_misc/<link>static/<using-clr>false</tt><tt><br>
</tt><tt> ;</tt><tt><br>
</tt><tt> </tt><br>
<u><br>
</u><u>Here are the custom rules/actions:</u><br>
<br>
<tt>actions compile-c++clr</tt><tt><br>
</tt><tt>{</tt><tt><br>
</tt><tt> $(.SETUP) $(.CC) @"@($(<[1]:W).rsp:E="$(>[1]:W)"
-Fo"$(<[1]:W)" -Yu"$(>[3]:D=)" -Fp"$(>[2]:W)" /clr
$(ASSEMBLY_INCLUDE_PATHS) $(ASSEMBLIES) $(CC_RSPLINE))"
$(.CC.FILTER)" > "$(<[1]:W).out"</tt><tt><br>
</tt><tt> set status=%ERRORLEVEL%</tt><tt><br>
</tt><tt> findstr /V /X "$(>[1]:D=)" "$(<[1]:W).out"</tt><tt><br>
</tt><tt> exit %status%</tt><tt><br>
</tt><tt>}</tt><tt><br>
</tt><tt><br>
</tt><tt>rule compile.c++clr ( targets + : sources * : properties *
)</tt><tt><br>
</tt><tt>{</tt><tt><br>
</tt><tt> set-setup-command $(targets) : $(properties) ;</tt><tt><br>
</tt><tt> set-assemblies $(<[1]) : $(properties) ;</tt><tt><br>
</tt><tt> get-rspline $(targets) : -TP ;</tt><tt><br>
</tt><tt> compile-c++clr $(<) : $(>) [ on $(<) return
$(PCH_FILE) ] [ on $(<) return $(PCH_HEADER) ] ;</tt><tt><br>
</tt><tt>}</tt><tt><br>
</tt><tt><br>
</tt><tt>actions link.clr.dll bind DEF_FILE
LIBRARIES_MENTIONED_BY_FILE</tt><tt><br>
</tt><tt>{</tt><tt><br>
</tt><tt> $(.SETUP) $(.LD) /DLL $(LINKFLAGS) /out:"$(<[1]:W)"
/LIBPATH:"$(LINKPATH:W)" /def:"$(DEF_FILE)" $(OPTIONS)
@"@($(<[1]:W).rsp:E=$(.nl)"$(>)"
$(.nl)$(LIBRARIES_MENTIONED_BY_FILE) $(.nl)$(LIBRARIES)
$(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_ST).lib"
$(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_SA).lib")"
$(MANIFEST_DEPENDENCIES)</tt><tt><br>
</tt><tt> if %ERRORLEVEL% NEQ 0 EXIT %ERRORLEVEL%</tt><tt><br>
</tt><tt>}</tt><tt><br>
</tt><tt><br>
</tt><tt>rule link.clr.dll ( targets + : sources * : properties * )</tt><tt><br>
</tt><tt>{</tt><tt><br>
</tt><tt> set-setup-command $(targets) : $(properties) ;</tt><tt><br>
</tt><tt> set-manifest-dependencies $(<[1]) : $(properties) ;</tt><tt><br>
</tt><tt> DEPENDS $(<) : [ on $(<) return $(DEF_FILE) ] ;</tt><tt><br>
</tt><tt> if <embed-manifest>on in $(properties)</tt><tt><br>
</tt><tt> {</tt><tt><br>
</tt><tt> msvc.manifest.dll $(targets) : $(sources) :
$(properties) ;</tt><tt><br>
</tt><tt> }</tt><tt><br>
</tt><tt> copy-assemblies $(<[1]) : $(properties) ;</tt><tt><br>
</tt><tt>}</tt><br>
<br>
<u><br>
</u><u>Here are the custom features:</u><br>
<tt><br>
</tt><tt>feature.feature assembly :
: free dependency ;</tt><tt><br>
</tt><tt>feature.feature assembly-dependency :
: free dependency ;</tt><tt><br>
</tt><tt>feature.feature assembly-dependency-ex :
: free ;</tt><tt><br>
</tt><tt>feature.feature manifest-dependency :
: free dependency ;</tt><tt><br>
</tt><tt>feature.feature configuration-file :
: free dependency ;</tt><tt><br>
</tt><tt>feature.feature using-clr : false true
: composite ;</tt><tt><br>
</tt><tt>feature.compose <using-clr>true :
<asynch-exceptions>on <runtime-link>shared ;<br>
<br>
generators.register [ new msvc-linking-generator
msvc.link.clr.dll : OBJ SEARCHED_LIB STATIC_LIB : SHARED_LIB :
<toolset>msvc <using-clr>true ] ;<br>
generators.override msvc.link.clr.dll : msvc.link.dll ;<br>
<br>
generators.register-c-compiler msvc.compile.c++clr : CPP : OBJ :
<toolset>msvc <using-clr>true ;</tt><br>
<br>
<u><br>
</u><u>Here are some utility functions used in the above actions:</u><br>
<tt><br>
</tt><tt>
#</tt><tt><br>
</tt><tt>
# Add /FU and /AI flags for targets using /clr</tt><tt><br>
</tt><tt>
#</tt><tt><br>
</tt><tt>
rule set-assemblies ( target : properties * )</tt><tt><br>
</tt><tt>
{</tt><tt><br>
</tt><tt>
local assemblies-string ;</tt><tt><br>
</tt><tt>
local assemblies = [ feature.get-values <assembly> :
$(properties) ] ;</tt><tt><br>
</tt><tt>
if $(assemblies)</tt><tt><br>
</tt><tt>
{</tt><tt><br>
</tt><tt>
for local assembly in $(assemblies)</tt><tt><br>
</tt><tt>
{</tt><tt><br>
</tt><tt>
local assembly-path = [ $(assembly).name ] ;</tt><tt><br>
</tt><tt>
if $(assembly-path:S) != ".pdb"</tt><tt><br>
</tt><tt>
{</tt><tt><br>
</tt><tt>
if ! [ path.is-rooted $(assembly-path) ]</tt><tt><br>
</tt><tt>
{</tt><tt><br>
</tt><tt>
assembly-path = [ path.join [ $(assembly).path
] $(assembly-path:D=) ] ;</tt><tt><br>
</tt><tt>
}</tt><tt><br>
</tt><tt>
assembly-path = [ path.native $(assembly-path) ] ;</tt><tt><br>
</tt><tt>
assemblies-string += " /FU\"$(assembly-path)\"" ;</tt><tt><br>
</tt><tt>
}</tt><tt><br>
</tt><tt>
}</tt><tt><br>
</tt><tt>
}</tt><tt><br>
</tt><tt>
ASSEMBLIES on $(target) = $(assemblies-string) ;</tt><tt><br>
</tt><tt>
</tt><tt><br>
</tt><tt>
# add /AI flags for each assembly-dependency's (unique)
directory</tt><tt><br>
</tt><tt>
local assembly-include-string ;</tt><tt><br>
</tt><tt>
local assembly-dependencies = [ feature.get-values
<assembly-dependency> : $(properties) ] ;</tt><tt><br>
</tt><tt>
if $(assembly-dependencies)</tt><tt><br>
</tt><tt>
{</tt><tt><br>
</tt><tt>
local assembly-include-paths ;</tt><tt><br>
</tt><tt>
for local dependency in $(assembly-dependencies)</tt><tt><br>
</tt><tt>
{</tt><tt><br>
</tt><tt>
local dependency-path = [ $(dependency).name ] ;</tt><tt><br>
</tt><tt>
if ! [ path.is-rooted $(dependency-path) ]</tt><tt><br>
</tt><tt>
{</tt><tt><br>
</tt><tt>
dependency-path = [ path.join [ $(dependency).path
] $(dependency-path:D=) ] ;</tt><tt><br>
</tt><tt>
}</tt><tt><br>
</tt><tt>
dependency-path = [ path.native $(dependency-path) ] ;</tt><tt><br>
</tt><tt>
dependency-path = $(dependency-path:D) ;</tt><tt><br>
</tt><tt>
if ! $(dependency-path) in $(assembly-include-paths)</tt><tt><br>
</tt><tt>
{</tt><tt><br>
</tt><tt>
assembly-include-paths += $(dependency-path) ;</tt><tt><br>
</tt><tt>
assembly-include-string += "
/AI\"$(dependency-path)\"" ;</tt><tt><br>
</tt><tt>
}</tt><tt><br>
</tt><tt>
}</tt><tt><br>
</tt><tt>
}</tt><tt><br>
</tt><tt>
ASSEMBLY_INCLUDE_PATHS on $(target) =
$(assembly-include-string) ;</tt><tt><br>
</tt><tt>
}</tt><tt><br>
</tt><tt><br>
</tt><tt>#</tt><tt><br>
</tt><tt># Add /MANIFESTDEPENDENCY flags (primarily for side-by-side
loading of COM DLLs)</tt><tt><br>
</tt><tt>#</tt><tt><br>
</tt><tt>local rule set-manifest-dependencies ( target : properties
* )</tt><tt><br>
</tt><tt>{</tt><tt><br>
</tt><tt> local manifest-dependencies-string ;</tt><tt><br>
</tt><tt> local manifest-dependencies = [ feature.get-values
<manifest-dependency> : $(properties) ] ;</tt><tt><br>
</tt><tt> if $(manifest-dependencies)</tt><tt><br>
</tt><tt> {</tt><tt><br>
</tt><tt> # type='win32' name='<assembly_basename>'
version='<assembly_version>'</tt><tt><br>
</tt><tt> for local dependency in $(manifest-dependencies)</tt><tt><br>
</tt><tt> {</tt><tt><br>
</tt><tt> local dependency-path = [ path.native [
$(dependency).name ] ] ;</tt><tt><br>
</tt><tt> local dependency-version = [ MATCH
"FileVersion: ([0-9\\.]+)" : [ SHELL "ShowVer.exe
$(dependency-path)" ] ] ;</tt><tt><br>
</tt><tt> </tt><tt><br>
</tt><tt> # unknown version will cause a runtime-error;
is there a better solution?</tt><tt><br>
</tt><tt> dependency-version ?= "unknown" ;</tt><tt><br>
</tt><tt> </tt><tt><br>
</tt><tt> # the name of the manifest can not match the
basename of the DLL because of a Windows XP loader bug</tt><tt><br>
</tt><tt> manifest-dependencies-string += "
/MANIFESTDEPENDENCY:\"type='win32' name='$(dependency-path:B).SxS'
version='$(dependency-version)'\"" ;</tt><tt><br>
</tt><tt> }</tt><tt><br>
</tt><tt> }</tt><tt><br>
</tt><tt> MANIFEST_DEPENDENCIES on $(target) =
$(manifest-dependencies-string) ;</tt><tt><br>
</tt><tt>}</tt><tt><br>
</tt><tt><br>
</tt><tt>#</tt><tt><br>
</tt><tt># Copy .NET assemblies and their native DLL dependencies to
the target's directory;</tt><tt><br>
</tt><tt># Also .NET applications may need a side-by-side
configuration file that must be named like $(target).exe.config -
copy that if necessary</tt><tt><br>
</tt><tt>#</tt><tt><br>
</tt><tt>rule copy-assemblies ( target : properties * )</tt><tt><br>
</tt><tt>{</tt><tt><br>
</tt><tt> local assemblies = [ feature.get-values
<assembly> : $(properties) ] ;</tt><tt><br>
</tt><tt> assemblies += [ feature.get-values
<assembly-dependency> : $(properties) ] ;</tt><tt><br>
</tt><tt> if $(assemblies)</tt><tt><br>
</tt><tt> {</tt><tt><br>
</tt><tt> local target-path = [ on $(target) return $(LOCATE)
] ;</tt><tt><br>
</tt><tt> for local assembly in $(assemblies)</tt><tt><br>
</tt><tt> {</tt><tt><br>
</tt><tt> local assembly-path = [ $(assembly).name ] ;</tt><tt><br>
</tt><tt> if ! [ path.is-rooted $(assembly-path) ]</tt><tt><br>
</tt><tt> {</tt><tt><br>
</tt><tt> assembly-path = [ path.join [
$(assembly).path ] $(assembly-path:D=) ] ;</tt><tt><br>
</tt><tt> }</tt><tt><br>
</tt><tt> assembly-path = [ path.native $(assembly-path)
] ;</tt><tt><br>
</tt><tt> local assembly-at-target-filepath = [
path.native [ path.join $(target-path) $(assembly-path:D=) ] ] ;</tt><tt><br>
</tt><tt><br>
</tt><tt> if $(assembly-at-target-filepath:L) !=
$(assembly-path:L) &&</tt><tt><br>
</tt><tt> ! ( $(assembly-at-target-filepath:L) in
$(.unique-targets) )</tt><tt><br>
</tt><tt> {</tt><tt><br>
</tt><tt> .unique-targets +=
$(assembly-at-target-filepath:L) ;</tt><tt><br>
</tt><tt> if ! [ CHECK_IF_FILE
$(assembly-at-target-filepath:L) ]</tt><tt><br>
</tt><tt> {</tt><tt><br>
</tt><tt> common.hard-link
$(assembly-at-target-filepath) : $(assembly-path) ;</tt><tt><br>
</tt><tt> DEPENDS $(assembly-at-target-filepath)
: $(target-path) [ $(assembly).actualize ] ;</tt><tt><br>
</tt><tt> DEPENDS $(target) :
$(assembly-at-target-filepath) ;</tt><tt><br>
</tt><tt> #JAM_SEMAPHORE on $(target-filepath) =
"dotNetSemaphore" ;</tt><tt><br>
</tt><tt> #JAM_SEMAPHORE on $(target) =
"dotNetSemaphore" ;</tt><tt><br>
</tt><tt> }</tt><tt><br>
</tt><tt> }</tt><tt><br>
</tt><tt> }</tt><tt><br>
</tt><tt> }</tt><tt><br>
</tt><tt><br>
</tt><tt> # .NET applications may need a side-by-side
configuration file that must be named like $(target).exe.config</tt><tt><br>
</tt><tt> local configuration-file = [ feature.get-values
<configuration-file> : $(properties) ] ;</tt><tt><br>
</tt><tt> if $(configuration-file)</tt><tt><br>
</tt><tt> {</tt><tt><br>
</tt><tt> local target-path = [ on $(target) return $(LOCATE)
] ;</tt><tt><br>
</tt><tt> local configuration-file-path = [
$(configuration-file).name ] ;</tt><tt><br>
</tt><tt> if ! [ path.is-rooted $(configuration-file-path) ]</tt><tt><br>
</tt><tt> {</tt><tt><br>
</tt><tt> configuration-file-path = [ path.join [
$(configuration-file).path ] $(configuration-file-path:D=) ] ;</tt><tt><br>
</tt><tt> }</tt><tt><br>
</tt><tt> configuration-file-path = [ path.native
$(configuration-file-path) ] ;</tt><tt><br>
</tt><tt> local target-filepath = [ path.native [ path.join
$(target-path) $(configuration-file-path:D=) ] ] ;</tt><tt><br>
</tt><tt> if $(target-filepath) != $(configuration-file-path)
&&</tt><tt><br>
</tt><tt> ! ( $(configuration-file-path) in
$(.unique-targets) )</tt><tt><br>
</tt><tt> {</tt><tt><br>
</tt><tt> .unique-targets += $(configuration-file-path) ;</tt><tt><br>
</tt><tt> common.hard-link $(target-filepath) :
$(configuration-file-path) ;</tt><tt><br>
</tt><tt> DEPENDS $(target-filepath) : $(target-path) ;</tt><tt><br>
</tt><tt> DEPENDS $(target) : $(target-filepath) ;</tt><tt><br>
</tt><tt> #JAM_SEMAPHORE on $(target-filepath) =
"dotNetSemaphore" ;</tt><tt><br>
</tt><tt> #JAM_SEMAPHORE on $(target) = "dotNetSemaphore"
;</tt><tt><br>
</tt><tt> }</tt><tt><br>
</tt><tt> }</tt><tt><br>
</tt><tt>}</tt><br>
</body>
</html>
--------------21CA42BC0987BD6EF846758C--
--===============5245480630400970436==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
_______________________________________________
Unsubscribe & other changes: https://lists.boost.org/mailman/listinfo.cgi/boost-build
--===============5245480630400970436==--