Disable transformations with unchanged paths for assets in build dir

This relates to the build system: Transformations that does not change file name are called filters, this could e.g. be converting UTF-8 to UTF-16 or converting a property list to binary representation (without changing extension).

This currently works when the filter is applied to a file in the source directory, as we write the result to the build directory, but if the input is already in the build directory, we would create a new output with the same path, which would result in a malformed build file (multiple targets generate the same file and/or cycles in the dependency graph).

As a workaround, we only allow filters to be applied to files in the source directory. But it would be nice to lift this limitation.
This commit is contained in:
Allan Odgaard
2021-01-12 10:04:00 +01:00
parent 418de67329
commit 4e922dde99

View File

@@ -449,8 +449,9 @@ SHELL
derived_assets = [ ]
queue = [ initial_asset ]
enable_filters = true
while asset = queue.shift
if compiler = compiler_for(asset.file)
if compiler = compiler_for(asset.file, enable_filters: enable_filters)
if compiler.filter?
derived_assets += compiler.transform(asset, self)
else
@@ -459,6 +460,15 @@ SHELL
else
derived_assets << asset
end
# We disable filters after first iteration because filters do not change the
# file name and therefore can only be used when we go from source → build
# directory.
#
# Example of problem: file → expand variables → convert utf-8 to utf-16
# src/InfoPlist.strings → build/InfoPlist.strings → build/InfoPlist.strings
# Here we need to mangle all but the last file path.
enable_filters = false
end
derived_assets
@@ -502,7 +512,7 @@ SHELL
private
def compiler_for(file)
def compiler_for(file, enable_filters: true)
candidates = []
Plugin.plugins_of_type(Compiler).each do |klass|
@@ -521,8 +531,10 @@ SHELL
end unless klass.extensions.nil?
end
if match = candidates.max { |lhs, rhs| lhs[:ext].length <=> rhs[:ext].length }
match[:class].new(self, @context, match[:ext], match[:canonical_ext] || match[:ext], match[:dest_ext])
candidates.sort! { |lhs, rhs| lhs[:ext].length <=> rhs[:ext].length }
while match = candidates.pop
res = match[:class].new(self, @context, match[:ext], match[:canonical_ext] || match[:ext], match[:dest_ext])
return res if enable_filters || !res.filter?
end
end
end