nodejs/node · error · Exception
Multiple .def files
Error message
Multiple .def files
What it means
GetDefFile scans the target's sources for files ending in '.def' (module-definition files for the MSVC linker). A single .def is accepted and wired into linker flags; more than one is ambiguous and rejected, because the linker can only consume one definition file.
Source
Thrown at tools/gyp/pylib/gyp/msvs_emulation.py:619
lib(
"TargetMachine",
map={"1": "X86", "17": "X64", "3": "ARM"},
prefix="/MACHINE:",
)
lib("AdditionalOptions")
return libflags
def GetDefFile(self, gyp_to_build_path):
"""Returns the .def file from sources, if any. Otherwise returns None."""
spec = self.spec
if spec["type"] in ("shared_library", "loadable_module", "executable"):
def_files = [
s for s in spec.get("sources", []) if s.lower().endswith(".def")
]
if len(def_files) == 1:
return gyp_to_build_path(def_files[0])
elif len(def_files) > 1:
raise Exception("Multiple .def files")
return None
def _GetDefFileAsLdflags(self, ldflags, gyp_to_build_path):
""".def files get implicitly converted to a ModuleDefinitionFile for the
linker in the VS generator. Emulate that behaviour here."""
if def_file := self.GetDefFile(gyp_to_build_path):
ldflags.append('/DEF:"%s"' % def_file)
def GetPGDName(self, config, expand_special):
"""Gets the explicitly overridden pgd name for a target or returns None
if it's not overridden."""
config = self._TargetConfig(config)
output_file = self._Setting(("VCLinkerTool", "ProfileGuidedDatabase"), config)
if output_file:
output_file = expand_special(
self.ConvertVSMacros(output_file, config=config)
)
return output_fileView on GitHub (pinned to 1b2de5e052)
Solutions
- Find all '.def' files listed in the target's 'sources' and keep only the one you intend the linker to use.
- Remove the extra .def entries (or move them out of sources).
- Re-run gyp.
Example fix
// before 'sources': ['lib.def', 'other.def', 'main.c'] // after 'sources': ['lib.def', 'main.c']
Defensive patterns
Strategy: validation
Validate before calling
def_files = [s for s in target_dict.get('sources', []) if s.lower().endswith('.def')]
if target_dict.get('type') in ('shared_library', 'loadable_module', 'executable') and len(def_files) > 1:
raise ValueError(f'{target_dict["target_name"]}: multiple .def files: {def_files}') Type guard
def at_most_one_def_file(target_dict: dict) -> bool:
def_files = [s for s in target_dict.get('sources', []) if s.lower().endswith('.def')]
return len(def_files) <= 1 Prevention
- Designate exactly one .def as the linker definition per target.
- If multiple modules need exports, merge them into a single .def.
- Review sources lists after merging targets.
When it happens
Trigger: A target of type shared_library, loadable_module, or executable has two or more source files whose lowercased name ends with '.def'.
Common situations: Accidentally adding two .def files to sources; merging sources from another target that already contributed a .def; build tooling that drops a generated .def next to a hand-written one.
Related errors
- Multiple module definition files in one target, target %s li
- AddFileConfig: file "%s" not in project.
- expected string; got %r
- expected string list; got %r
- expected bool; got %r
AI-assisted analysis of nodejs/node@1b2de5e052 (2026-08-13).
Data as JSON: /api/errors/5576026abc879c48.
Report an issue: GitHub.