Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions src/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1624,6 +1624,12 @@ export async function parseLaunchConfigurations(
);
}
} else {
// If the binary has no extension, append .exe
// This ensures VS Code can properly link to the file in the output
// Note: No platform check needed here - this entire block is Windows-specific (see line 1553)
if (!path.extname(compilerTargetBinary)) {
compilerTargetBinary += ".exe";
}
logger.message(
localize(
"producing.target.binary",
Expand Down Expand Up @@ -1707,6 +1713,15 @@ export async function parseLaunchConfigurations(
linkerTool.arguments,
["out", "o"]
);
// On Windows, if the binary has no extension, append .exe
// This ensures VS Code can properly link to the file in the output
if (
linkerTargetBinary &&
process.platform === "win32" &&
!path.extname(linkerTargetBinary)
) {
linkerTargetBinary += ".exe";
}
logger.message(
localize(
"found.linker.command",
Expand Down
43 changes: 43 additions & 0 deletions src/test/fakeSuite/extension.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,49 @@ suite("Unit testing replacing characters in and outside of quotes", () => {
});
});

suite("Unit testing binary path extension handling", () => {
// Tests for the logic that appends .exe extension on Windows
// when binary paths have no extension (fixes issue #698)

test("path.extname returns empty string for paths without extension", () => {
expect(path.extname("app")).to.be.equal("");
expect(path.extname("/path/to/app")).to.be.equal("");
expect(path.extname("C:\\path\\to\\app")).to.be.equal("");
});

test("path.extname returns extension for paths with extension", () => {
expect(path.extname("app.exe")).to.be.equal(".exe");
expect(path.extname("/path/to/app.exe")).to.be.equal(".exe");
expect(path.extname("C:\\path\\to\\app.exe")).to.be.equal(".exe");
expect(path.extname("lib.dll")).to.be.equal(".dll");
expect(path.extname("file.out")).to.be.equal(".out");
});

test("Appending .exe only when no extension present", () => {
// Simulates the logic in parser.ts for appending .exe on Windows
const appendExeIfNoExtension = (binaryPath: string): string => {
if (!path.extname(binaryPath)) {
return binaryPath + ".exe";
}
return binaryPath;
};

// Paths without extension should get .exe appended
expect(appendExeIfNoExtension("app")).to.be.equal("app.exe");
expect(appendExeIfNoExtension("/path/to/app")).to.be.equal(
"/path/to/app.exe"
);
expect(appendExeIfNoExtension("C:\\path\\to\\app")).to.be.equal(
"C:\\path\\to\\app.exe"
);

// Paths with extension should remain unchanged
expect(appendExeIfNoExtension("app.exe")).to.be.equal("app.exe");
expect(appendExeIfNoExtension("lib.dll")).to.be.equal("lib.dll");
expect(appendExeIfNoExtension("file.out")).to.be.equal("file.out");
});
});

// TODO: refactor initialization and cleanup of each test
suite("Fake dryrun parsing", () => {
suiteSetup(async function (this: Mocha.Context) {
Expand Down