diff --git a/dotnet/private/common.bzl b/dotnet/private/common.bzl index 33de2af6..18664c6b 100644 --- a/dotnet/private/common.bzl +++ b/dotnet/private/common.bzl @@ -271,6 +271,7 @@ def collect_compile_info(name, deps, targeting_pack, exports, strict_deps): targeting_pack_overrides = {} framework_list = {} framework_files = [] + analyzer_dlls = [] if targeting_pack: targeting_pack_info = targeting_pack[DotnetTargetingPackInfo] @@ -286,6 +287,8 @@ def collect_compile_info(name, deps, targeting_pack, exports, strict_deps): if len(nuget_info.framework_list) == 0: framework_files.extend(compile_info.irefs) + analyzer_dlls.extend([a.basename for a in compile_info.analyzers + compile_info.analyzers_csharp + compile_info.analyzers_fsharp + compile_info.analyzers_vb]) + direct_analyzers.extend(compile_info.analyzers) direct_analyzers_csharp.extend(compile_info.analyzers_csharp) direct_analyzers_fsharp.extend(compile_info.analyzers_fsharp) @@ -312,10 +315,35 @@ def collect_compile_info(name, deps, targeting_pack, exports, strict_deps): if add_to_output: direct_iref.extend(assembly.irefs if name in assembly.internals_visible_to else assembly.refs) direct_ref.extend(assembly.refs) - direct_analyzers.extend(assembly.analyzers) - direct_analyzers_csharp.extend(assembly.analyzers_csharp) - direct_analyzers_fsharp.extend(assembly.analyzers_fsharp) - direct_analyzers_vb.extend(assembly.analyzers_vb) + + # Only add new analyzer DLLs that are not already in the list; for targets that use both + # a targetting pack and other framework dependencies we can end up with duplicates. + # eg: + # target_frameworks = ["net8.0"], + # deps = ["@paket.main//microsoft.aspnetcore.app.ref"], + # results in these duplicates: + # "Microsoft.AspNetCore.App.Analyzers.dll", + # "Microsoft.AspNetCore.App.CodeFixes.dll", + # "Microsoft.AspNetCore.Components.Analyzers.dll", + # "Microsoft.AspNetCore.Http.RequestDelegateGenerator.dll", + # "Microsoft.Extensions.Configuration.Binder.SourceGeneration.dll", + # "Microsoft.Extensions.Logging.Generators.dll" + new_analyzers = [a for a in assembly.analyzers if a.basename not in analyzer_dlls] + direct_analyzers.extend(new_analyzers) + analyzer_dlls.extend([a.basename for a in new_analyzers]) + + new_analyzers = [a for a in assembly.analyzers_csharp if a.basename not in analyzer_dlls] + direct_analyzers_csharp.extend(new_analyzers) + analyzer_dlls.extend([a.basename for a in new_analyzers]) + + new_analyzers = [a for a in assembly.analyzers_fsharp if a.basename not in analyzer_dlls] + direct_analyzers_fsharp.extend(new_analyzers) + analyzer_dlls.extend([a.basename for a in new_analyzers]) + + new_analyzers = [a for a in assembly.analyzers_vb if a.basename not in analyzer_dlls] + direct_analyzers_vb.extend(new_analyzers) + analyzer_dlls.extend([a.basename for a in new_analyzers]) + direct_compile_data.extend(assembly.compile_data) # We take all the exports of each dependency and add them @@ -333,10 +361,24 @@ def collect_compile_info(name, deps, targeting_pack, exports, strict_deps): add_to_output = False if add_to_output: transitive_ref.append(transitive_assembly) - transitive_analyzers.append(assembly.transitive_analyzers) - transitive_analyzers_csharp.append(assembly.transitive_analyzers_csharp) - transitive_analyzers_fsharp.append(assembly.transitive_analyzers_fsharp) - transitive_analyzers_vb.append(assembly.transitive_analyzers_vb) + + # avoid duplicate analyzers (see above) + new_analyzers = [a for a in assembly.transitive_analyzers.to_list() if a.basename not in analyzer_dlls] + transitive_analyzers.append(depset(new_analyzers)) + analyzer_dlls.extend([a.basename for a in new_analyzers]) + + new_analyzers = [a for a in assembly.transitive_analyzers_csharp.to_list() if a.basename not in analyzer_dlls] + transitive_analyzers_csharp.append(depset(new_analyzers)) + analyzer_dlls.extend([a.basename for a in new_analyzers]) + + new_analyzers = [a for a in assembly.transitive_analyzers_fsharp.to_list() if a.basename not in analyzer_dlls] + transitive_analyzers_fsharp.append(depset(new_analyzers)) + analyzer_dlls.extend([a.basename for a in new_analyzers]) + + new_analyzers = [a for a in assembly.transitive_analyzers_vb.to_list() if a.basename not in analyzer_dlls] + transitive_analyzers_vb.append(depset(new_analyzers)) + analyzer_dlls.extend([a.basename for a in new_analyzers]) + transitive_compile_data.append(assembly.transitive_compile_data) for file in framework_list.values(): @@ -757,8 +799,11 @@ def copy_files_to_dir(target_name, actions, is_windows, files, out_dir): inputs.append(src) outputs.append(dst) if is_windows: - script_body.append("if not exist \"{dir}\" @mkdir \"{dir}\" >NUL".format(dir = dst.dirname.replace("/", "\\"))) - script_body.append("@copy /Y \"{src}\" \"{dst}\" >NUL".format(src = src.path.replace("/", "\\"), dst = dst.path.replace("/", "\\"))) + script_body.append("if not exist \"{dir}\" mkdir \"{dir}\"".format(dir = dst.dirname.replace("/", "\\"))) + script_body.append("copy /Y \"{src}\" \"{dst}\" >NUL".format(src = src.path.replace("/", "\\"), dst = dst.path.replace("/", "\\"))) + script_body.append("if not exist \"{dst}\" echo Failed to copy to \"{dst}\"".format(dst = dst.path.replace("/", "\\"))) + script_body.append("if not exist \"{dst}\" exit /b 1".format(dst = dst.path.replace("/", "\\"))) + script_body.append("") else: script_body.append("mkdir -p {dir} && cp -f {src} {dst}".format(dir = shell.quote(dst.dirname), src = shell.quote(src.path), dst = shell.quote(dst.path))) @@ -809,10 +854,15 @@ def map_resource_arg(file, target_label, out_dll, language): # the basename of the file. simple_resource_name = "{}.{}".format(out_dll[:-4], file.basename) - if file.owner != None and file.owner.repo_name != target_label.repo_name: + if len(file.basename.split(".")) > 2: + # Resgen encourages naming resource files with dot-delimited full namespace. + # If named like this, we will use the full name as-is. + # eg Foo.Bar.a.b.c.resources + resource_name = file.basename + elif file.owner != None and file.owner.repo_name != target_label.repo_name: # Fallback to the basename if the file comes from a different repository. resource_name = simple_resource_name - if not file.short_path.startswith(target_label.package): + elif not file.short_path.startswith(target_label.package) and not file.short_path.startswith("bazel-bin/" + target_label.package): # Fallback to the basename if the file is not in the target's package, because # the path will not be normalized. resource_name = simple_resource_name diff --git a/dotnet/private/rules/csharp/actions/csharp_assembly.bzl b/dotnet/private/rules/csharp/actions/csharp_assembly.bzl index 7d948f71..899576c0 100644 --- a/dotnet/private/rules/csharp/actions/csharp_assembly.bzl +++ b/dotnet/private/rules/csharp/actions/csharp_assembly.bzl @@ -353,7 +353,7 @@ def AssemblyAction( resource_assemblies = [], pdbs = [out_pdb] if out_pdb else [], xml_docs = [out_xml] if out_xml else [], - data = data, + data = data + out_appsettings, appsetting_files = depset(out_appsettings), native = [], deps = depset( diff --git a/dotnet/private/rules/fsharp/actions/fsharp_assembly.bzl b/dotnet/private/rules/fsharp/actions/fsharp_assembly.bzl index 0103be5b..2fa05783 100644 --- a/dotnet/private/rules/fsharp/actions/fsharp_assembly.bzl +++ b/dotnet/private/rules/fsharp/actions/fsharp_assembly.bzl @@ -306,7 +306,7 @@ def AssemblyAction( resource_assemblies = [], pdbs = [out_pdb] if out_pdb else [], xml_docs = [out_xml] if out_xml else [], - data = data, + data = data + out_appsettings, appsetting_files = depset(out_appsettings), native = [], deps = depset([dep[DotnetAssemblyRuntimeInfo] for dep in deps], transitive = [dep[DotnetAssemblyRuntimeInfo].deps for dep in deps]),