1# Copyright 2003 Dave Abrahams 2# Copyright 2002, 2003 Rene Rivera 3# Copyright 2002, 2003, 2004, 2005 Vladimir Prus 4# Distributed under the Boost Software License, Version 1.0. 5# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) 6 7# Defines the "symlink" special target. 'symlink' targets make symbolic links 8# to the sources. 9 10import targets modules path class os feature project property-set ; 11 12.count = 0 ; 13 14feature.feature symlink-location : project-relative build-relative : incidental ; 15 16# The class representing "symlink" targets. 17# 18class symlink-targets : basic-target 19{ 20 import numbers modules class property project path ; 21 22 rule __init__ ( 23 project 24 : targets * 25 : sources * 26 ) 27 { 28 # Generate a fake name for now. Need unnamed targets eventually. 29 local c = [ modules.peek symlink : .count ] ; 30 modules.poke symlink : .count : [ numbers.increment $(c) ] ; 31 local fake-name = symlink#$(c) ; 32 33 basic-target.__init__ $(fake-name) : $(project) : $(sources) ; 34 35 # Remember the targets to map the sources onto. Pad or truncate 36 # to fit the sources given. 37 self.targets = ; 38 for local source in $(sources) 39 { 40 if $(targets) 41 { 42 self.targets += $(targets[1]) ; 43 targets = $(targets[2-]) ; 44 } 45 else 46 { 47 self.targets += $(source) ; 48 } 49 } 50 51 # The virtual targets corresponding to the given targets. 52 self.virtual-targets = ; 53 } 54 55 rule construct ( name : source-targets * : property-set ) 56 { 57 local i = 1 ; 58 for local t in $(source-targets) 59 { 60 local s = $(self.targets[$(i)]) ; 61 local a = [ class.new action $(t) : symlink.ln : $(property-set) ] ; 62 local vt = [ class.new file-target $(s:D=) 63 : [ $(t).type ] : $(self.project) : $(a) ] ; 64 65 # Place the symlink in the directory relative to the project 66 # location, instead of placing it in the build directory. 67 if [ property.select <symlink-location> : [ $(property-set).raw ] ] = <symlink-location>project-relative 68 { 69 $(vt).set-path [ path.root $(s:D) [ $(self.project).get location ] ] ; 70 } 71 72 self.virtual-targets += $(vt) ; 73 i = [ numbers.increment $(i) ] ; 74 } 75 return [ property-set.empty ] $(self.virtual-targets) ; 76 } 77} 78 79# Creates a symbolic link from a set of targets to a set of sources. 80# The targets and sources map one to one. The symlinks generated are 81# limited to be the ones given as the sources. That is, the targets 82# are either padded or trimmed to equate to the sources. The padding 83# is done with the name of the corresponding source. For example:: 84# 85# symlink : one two ; 86# 87# Is equal to:: 88# 89# symlink one two : one two ; 90# 91# Names for symlink are relative to the project location. They cannot 92# include ".." path components. 93rule symlink ( 94 targets * 95 : sources * 96 ) 97{ 98 local project = [ project.current ] ; 99 100 return [ targets.main-target-alternative 101 [ class.new symlink-targets $(project) : $(targets) : 102 # Note: inline targets are not supported for symlink, intentionally, 103 # since it's used to linking existing non-local targets. 104 $(sources) ] ] ; 105} 106 107rule ln 108{ 109 local os ; 110 if [ modules.peek : UNIX ] { os = UNIX ; } 111 else { os ?= [ os.name ] ; } 112 # Remember the path to make the link relative to where the symlink is located. 113 local path-to-source = [ path.relative-to 114 [ path.make [ on $(<) return $(LOCATE) ] ] 115 [ path.make [ on $(>) return $(LOCATE) ] ] ] ; 116 if $(path-to-source) = . 117 { 118 PATH_TO_SOURCE on $(<) = "" ; 119 } 120 else 121 { 122 PATH_TO_SOURCE on $(<) = [ path.native $(path-to-source) ] ; 123 } 124 ln-$(os) $(<) : $(>) ; 125} 126 127actions ln-UNIX 128{ 129 ln -f -s '$(>:D=:R=$(PATH_TO_SOURCE))' '$(<)' 130} 131 132# there is a way to do this; we fall back to a copy for now 133actions ln-NT 134{ 135 echo "NT symlinks not supported yet, making copy" 136 del /f /q "$(<)" 2>nul >nul 137 copy "$(>)" "$(<)" $(NULL_OUT) 138} 139 140IMPORT $(__name__) : symlink : : symlink ; 141