You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by "ammachado (via GitHub)" <gi...@apache.org> on 2026/07/13 14:39:53 UTC

[PR] CAMEL-23703: camel-launcher - native camel.exe bootstrap for Windows [camel]

ammachado opened a new pull request, #24665:
URL: https://github.com/apache/camel/pull/24665

   # Description
   
   Slice of the larger CAMEL-23703 unified Camel CLI package distribution effort, split out for focused review. This branch is **independent** of the other CAMEL-23703 slices and targets `main` directly.
   
   It adds a native x64 **`bin/camel.exe`** to the `camel-launcher` Windows distribution, alongside `bin/camel.bat`. `camel.exe` is a thin bootstrap: it locates the adjacent `camel.bat`, forwards all arguments verbatim (preserving spaces and Unicode), inherits the standard streams, and returns the child exit code. It performs no Java discovery or option parsing itself, that all remains in `camel.bat`.
   
   The executable exists so package managers that require a genuine executable command (such as WinGet's portable installer) can expose `camel` directly. Direct users may keep invoking `bin\camel.bat`; both behave identically. Windows ARM64 and x86 are not yet supported.
   
   Included: the C bootstrap source and its README, Maven profiles that build and gate the native image, inclusion of `camel.exe` in the bin archives, a Windows behavioral test, a Windows x64 CI workflow, and an upgrade-guide note.
   
   # Target
   
   - [x] I checked that the commit is targeting the correct branch (Camel 4 uses the `main` branch)
   
   # Tracking
   - [x] If this is a large change, bug fix, or code improvement, I checked there is a [JIRA issue](https://issues.apache.org/jira/browse/CAMEL-23703) filed for the change (usually before you start working on it).
   
   # Apache Camel coding standards and style
   
   - [x] I checked that each commit in the pull request has a meaningful subject line and body.
   
   - [ ] I have run `mvn clean install -DskipTests` locally from root folder and I have committed all auto-generated changes.
   
     _`mvn formatter:format impsort:sort` has been applied. A full-repo build verification is still in progress; this PR is intentionally opened as a draft until that completes._
   
   # AI-assisted contributions
   
   - [x] If this PR includes AI-generated code, commits have proper co-authorship attribution (e.g., `Co-authored-by` trailers) and the PR description identifies the AI tool used.
   
   ---
   _Claude Code (Opus 4.8) on behalf of ammachado_
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] CAMEL-23703: tooling/camel-exe - native camel.exe bootstrap for Windows [camel]

Posted by "davsclaus (via GitHub)" <gi...@apache.org>.
davsclaus commented on code in PR #24665:
URL: https://github.com/apache/camel/pull/24665#discussion_r3581351256


##########
dsl/camel-jbang/camel-launcher/src/test/java/org/apache/camel/dsl/jbang/launcher/CamelLauncherWindowsExeIT.java:
##########
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.dsl.jbang.launcher;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.stream.Stream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.EnabledIfSystemProperty;
+import org.junit.jupiter.api.condition.EnabledOnOs;
+import org.junit.jupiter.api.condition.OS;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Release gate for the native {@code camel.exe} packaged into the launcher distribution. Runs during {@code verify}
+ * when {@code -Dcamel.launcher.requireWindowsExe=true} is set on a Windows x64 host.
+ */
+@EnabledOnOs(OS.WINDOWS)
+@EnabledIfSystemProperty(named = "camel.launcher.requireWindowsExe", matches = "true")
+class CamelLauncherWindowsExeIT {
+
+    private static final Path TARGET = Paths.get("target");
+    private static final Path STAGED_EXE = TARGET.resolve("camel.exe");
+
+    @Test
+    void stagedCamelExeExists() {
+        assertTrue(Files.isRegularFile(STAGED_EXE),
+                "target/camel.exe must be present before packaging the launcher distribution");
+    }
+
+    @Test
+    void binArchiveIncludesCamelExe() throws IOException {

Review Comment:
   [LOW] `archive.getEntry("bin/camel.exe")` uses an exact path, but the assembly descriptor (`bin.xml`) does not set `<includeBaseDirectory>false</includeBaseDirectory>` — Maven Assembly Plugin defaults to `true`, which prefixes entries with `camel-launcher-VERSION-bin/`. This means `getEntry("bin/camel.exe")` would return null.
   
   The CI PowerShell assertion handles this correctly with wildcard matching (`*/bin/camel.exe`). Consider iterating entries with a suffix match here as well, or setting `includeBaseDirectory` to `false` in the assembly descriptor if that's the intended layout.
   
   This test is double-gated (`@EnabledOnOs(OS.WINDOWS)` + `@EnabledIfSystemProperty`) so it doesn't affect CI, but would fail for a developer running `mvn verify -Dcamel.launcher.requireWindowsExe=true` on Windows.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] CAMEL-23703: tooling/camel-exe - native camel.exe bootstrap for Windows [camel]

Posted by "davsclaus (via GitHub)" <gi...@apache.org>.
davsclaus commented on code in PR #24665:
URL: https://github.com/apache/camel/pull/24665#discussion_r3584819889


##########
docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_22.adoc:
##########
@@ -80,6 +80,16 @@ The Gentoo `java-config` auto-detection and the IBM AIX `$JAVA_HOME/jre/sh/java`
 removed; set `JAVA_HOME` or `JAVACMD` explicitly on those platforms.
 `JAVA_OPTS` handling is unchanged: when unset, the default `-Xmx512m` heap is applied.
 
+==== Native `camel.exe` in the launcher distribution
+
+The `camel-launcher` Windows distribution now ships a native x64 `bin/camel.exe`
+alongside `bin/camel.bat`. `camel.exe` is a thin bootstrap: it forwards all
+arguments to the adjacent `camel.bat` (preserving spaces and Unicode) and returns
+its exit code. It exists so package managers that require a genuine executable
+command (such as WinGet's portable installer) can expose `camel` directly. Direct
+users may continue to invoke `bin\camel.bat`; both behave identically. Windows
+ARM64 and x86 are not yet supported.

Review Comment:
   Please remove the last sentence — x64 covers essentially all Windows users, and ARM64 can run x64 binaries via Windows' built-in emulation, so no one is blocked.
   
   ```suggestion
   users may continue to invoke `bin\camel.bat`; both behave identically.
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] CAMEL-23703: camel-launcher - native camel.exe bootstrap for Windows [camel]

Posted by "github-actions[bot] (via GitHub)" <gi...@apache.org>.
github-actions[bot] commented on PR #24665:
URL: https://github.com/apache/camel/pull/24665#issuecomment-4959163054

   :star2: Thank you for your contribution to the Apache Camel project! :star2:
     :robot: CI automation will test this PR automatically.
   
     :camel: Apache Camel Committers, please review the following items:
   
     * First-time contributors **require MANUAL approval** for the GitHub Actions to run
     * You can use the command `/component-test (camel-)component-name1 (camel-)component-name2..` to request a test from the test bot although they are normally detected and executed by CI.
     * You can label PRs using `skip-tests` and `test-dependents` to fine-tune the checks executed by this PR.
     * Build and test logs are available in the summary page. **Only** [Apache Camel committers](https://camel.apache.org/community/team/#committers) have access to the summary.
     
     :warning: Be careful when sharing logs. Review their contents before sharing them publicly.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] CAMEL-23703: tooling/camel-exe - native camel.exe bootstrap for Windows [camel]

Posted by "davsclaus (via GitHub)" <gi...@apache.org>.
davsclaus commented on code in PR #24665:
URL: https://github.com/apache/camel/pull/24665#discussion_r3573547428


##########
.github/workflows/camel-launcher-windows.yml:
##########
@@ -0,0 +1,128 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+name: Camel launcher Windows build
+
+on:
+  push:
+    branches:
+      - main
+  pull_request:
+    branches:
+      - main
+  workflow_dispatch:
+
+concurrency:
+  group: ${{ github.workflow }}-${{ github.ref }}
+  cancel-in-progress: true
+
+permissions:
+  contents: read
+
+jobs:
+  detect-changes:
+    runs-on: ubuntu-latest
+    outputs:
+      camel-exe: ${{ steps.changes.outputs.camel-exe }}
+      camel-launcher: ${{ steps.changes.outputs.camel-launcher }}
+    steps:
+      - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
+        with:
+          persist-credentials: false
+          # 50 commits covers any reasonable push batch; PRs fetch the base ref below.
+          fetch-depth: 50
+      - id: changes
+        run: |
+          if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
+            echo "camel-exe=true" >> "$GITHUB_OUTPUT"
+            echo "camel-launcher=true" >> "$GITHUB_OUTPUT"
+            exit 0
+          fi
+
+          if [ "${{ github.event_name }}" = "pull_request" ]; then
+            git fetch origin "${{ github.base_ref }}" --depth=1
+            CHANGED="$(git diff --name-only "origin/${{ github.base_ref }}"...HEAD)"
+          else
+            CHANGED="$(git diff --name-only "${{ github.event.before }}" "${{ github.sha }}")"
+          fi
+
+          echo "Changed files:"
+          echo "$CHANGED"
+
+          camel_exe=false
+          camel_launcher=false
+
+          if echo "$CHANGED" | grep -qE '^(tooling/camel-exe/|\.github/workflows/camel-launcher-windows\.yml)'; then
+            camel_exe=true
+          fi
+
+          if echo "$CHANGED" | grep -qE '^(dsl/camel-jbang/camel-launcher/|tooling/camel-exe/|\.github/workflows/camel-launcher-windows\.yml)'; then
+            camel_launcher=true
+          fi
+
+          echo "camel-exe=$camel_exe" >> "$GITHUB_OUTPUT"
+          echo "camel-launcher=$camel_launcher" >> "$GITHUB_OUTPUT"
+
+  camel-exe:
+    needs: detect-changes
+    if: github.event_name == 'workflow_dispatch' || needs.detect-changes.outputs.camel-exe == 'true'
+    runs-on: windows-2022
+    steps:
+      - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
+        with:
+          persist-credentials: false
+      - name: Set up JDK 21
+        uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
+        with:
+          distribution: 'temurin'
+          java-version: '21'
+          cache: 'maven'
+      - name: Build and test native camel.exe
+        shell: cmd
+        run: |
+          for /f "usebackq delims=" %%i in (`"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath`) do set "VSINSTALL=%%i"
+          call "%VSINSTALL%\VC\Auxiliary\Build\vcvars64.bat"
+          mvn -B -ntp -pl buildingtools install -DskipTests
+          mvn -B -ntp -pl tooling/camel-exe verify -Dcamel.exe.requireWindowsExe=true
+
+  camel-launcher-windows:
+    needs: detect-changes
+    if: github.event_name == 'workflow_dispatch' || needs.detect-changes.outputs.camel-launcher == 'true'
+    runs-on: windows-2022
+    steps:
+      - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
+        with:
+          persist-credentials: false
+      - name: Set up JDK 21
+        uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
+        with:
+          distribution: 'temurin'
+          java-version: '21'
+          cache: 'maven'
+      - name: Build launcher with native camel.exe
+        shell: cmd
+        run: |
+          for /f "usebackq delims=" %%i in (`"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath`) do set "VSINSTALL=%%i"
+          call "%VSINSTALL%\VC\Auxiliary\Build\vcvars64.bat"
+          mvn -B -ntp -pl buildingtools,tooling/camel-exe,dsl/camel-jbang/camel-launcher -am install -DskipTests -Dcamel.launcher.requireWindowsExe=true
+      - name: Assert archive carries bin/camel.exe
+        shell: pwsh
+        run: |
+          $zip = Get-ChildItem dsl/camel-jbang/camel-launcher/target/camel-launcher-*-bin.zip | Select-Object -First 1
+          Add-Type -AssemblyName System.IO.Compression.FileSystem
+          $names = [System.IO.Compression.ZipFile]::OpenRead($zip.FullName).Entries.FullName
+          if ($names -notcontains 'bin/camel.exe') { throw 'camel.exe missing from launcher archive' }

Review Comment:
   This assertion is currently failing in CI — the ZIP is produced but `bin/camel.exe` is not inside it. The `camel-exe` job passes (native build is fine), so the issue is in how the launcher integrates the artifact.
   
   Worth checking whether the `maven-dependency-plugin:copy` execution at `generate-resources` phase in `camel-launcher/pom.xml` actually runs before the assembly plugin, and whether the `include-camel-exe` profile activates correctly on the CI Windows runner.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] CAMEL-23703: tooling/camel-exe - native camel.exe bootstrap for Windows [camel]

Posted by "ammachado (via GitHub)" <gi...@apache.org>.
ammachado commented on PR #24665:
URL: https://github.com/apache/camel/pull/24665#issuecomment-4960780144

   For the reviewers: should this feature trigger a `camel-launcher` build, or that can be handled during the release?


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] CAMEL-23703: tooling/camel-exe - native camel.exe bootstrap for Windows [camel]

Posted by "davsclaus (via GitHub)" <gi...@apache.org>.
davsclaus merged PR #24665:
URL: https://github.com/apache/camel/pull/24665


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] CAMEL-23703: camel-launcher - native camel.exe bootstrap for Windows [camel]

Posted by "github-actions[bot] (via GitHub)" <gi...@apache.org>.
github-actions[bot] commented on PR #24665:
URL: https://github.com/apache/camel/pull/24665#issuecomment-4959555274

   <!-- ci-tested-modules -->
   :test_tube: **CI tested the following changed modules:**
   
   - `docs`
   - `dsl/camel-jbang/camel-launcher`
   
   ---
   
   <details><summary>:microscope: Scalpel shadow comparison — Scalpel: 3 tested, 0 compile-only — current: 1 all tested</summary>
   
   [Maveniverse Scalpel](https://github.com/maveniverse/scalpel) detected **3 affected modules** (current approach: 1).
   
   <details><summary>:warning: Modules only in Scalpel (2)</summary>
   
   - `camel-launcher`
   - `docs`
   
   </details>
   
   **Skip-tests mode would test 3 modules** (2 direct + 1 downstream), **skip tests for 0** (generated code, meta-modules)
   
   <details><summary>Modules Scalpel would test (3)</summary>
   
   - `camel-launcher`
   - `camel-launcher-container`
   - `docs`
   
   </details>
   
   > :information_source: Shadow mode — Scalpel observes but does not affect test execution. [Learn more](https://github.com/maveniverse/scalpel)
   
   </details>
   
   :bulb: **Manual integration tests recommended:**
   
   > You modified `dsl/camel-jbang/camel-launcher`. The related integration tests in `dsl/camel-jbang/camel-jbang-it` are excluded from CI. Consider running them manually:
   > ```
   > mvn verify -f dsl/camel-jbang/camel-jbang-it -Djbang-it-test
   > ```
   
   <details><summary>All tested modules (3 modules)</summary>
   
   - Camel :: Docs
   - Camel :: Launcher
   - Camel :: Launcher :: Container
   
   </details>
   
   ---
   :gear: [View full build and test results](https://github.com/apache/camel/actions/runs/29259823537)


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] CAMEL-23703: tooling/camel-exe - native camel.exe bootstrap for Windows [camel]

Posted by "davsclaus (via GitHub)" <gi...@apache.org>.
davsclaus commented on PR #24665:
URL: https://github.com/apache/camel/pull/24665#issuecomment-4977368739

   ⏺ x64 covers the vast majority of Windows machines today — essentially all Intel and AMD desktops, laptops, and servers from the last 15+ years. It's the safe default.
   
     ARM64 — Windows on ARM (Surface Pro X, Copilot+ PCs with Snapdragon X) is growing but still a small share. The important nuance: Windows 11 on ARM can run x64 binaries via built-in emulation, so the x64
     camel.exe will still work on those machines — just not as a native ARM binary. Users aren't blocked, they just pay a small emulation overhead for a thin launcher that does almost nothing.
   
     x86 (32-bit) — effectively dead. Windows 11 doesn't even ship a 32-bit version. Only legacy systems.
   
     So the "not yet supported" note is technically accurate but practically inconsequential — x64 covers everyone, and ARM64 users can run it via emulation. Want me to simplify the upgrade guide entry to drop
     the ARM64/x86 caveat, or keep it?


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] CAMEL-23703: tooling/camel-exe - native camel.exe bootstrap for Windows [camel]

Posted by "gnodet (via GitHub)" <gi...@apache.org>.
gnodet commented on code in PR #24665:
URL: https://github.com/apache/camel/pull/24665#discussion_r3572911845


##########
tooling/camel-exe/src/main/native/camel.c:
##########
@@ -0,0 +1,106 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * camel.exe - minimal WinGet-compatible bootstrap for the Camel CLI launcher.
+ *
+ * It locates the camel.bat sitting in the same directory, forwards the caller's
+ * exact command-line tail (preserving Unicode and Windows quoting), inherits the
+ * standard streams, and returns the child process exit code. It performs NO Java
+ * discovery and NO Camel option parsing; that all lives in camel.bat.
+ */
+
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <wchar.h>
+
+/* Return the command-line tail after argv[0], preserving the caller's quoting. */
+static LPWSTR skip_argv0(LPWSTR cmd) {
+    LPWSTR p = cmd;
+    if (*p == L'"') {
+        p++;
+        while (*p && *p != L'"') {
+            p++;
+        }
+        if (*p == L'"') {
+            p++;
+        }
+    } else {
+        while (*p && *p != L' ' && *p != L'\t') {
+            p++;
+        }
+    }
+    while (*p == L' ' || *p == L'\t') {
+        p++;
+    }
+    return p;
+}
+
+int wmain(void) {
+    wchar_t exePath[MAX_PATH];
+    DWORD n = GetModuleFileNameW(NULL, exePath, MAX_PATH);
+    if (n == 0 || n >= MAX_PATH) {
+        fwprintf(stderr, L"camel: launcher path exceeds MAX_PATH (%d chars) or cannot be resolved\n", MAX_PATH);
+        return 1;
+    }
+
+    /* Strip the exe filename, leaving the directory. */
+    wchar_t *slash = wcsrchr(exePath, L'\\');
+    if (slash == NULL) {
+        fwprintf(stderr, L"camel: unexpected launcher path\n");
+        return 1;
+    }
+    *slash = L'\0';
+
+    LPWSTR tail = skip_argv0(GetCommandLineW());
+
+    /*
+     * cmd.exe /S /C ""<dir>\camel.bat" <tail>"
+     * With /S and a command wrapped in an outer pair of quotes, cmd strips the
+     * first and last quote and executes the remainder verbatim, so the inner
+     * quotes around the (possibly spaced/Unicode) camel.bat path survive.
+     */
+    size_t cap = wcslen(exePath) + wcslen(tail) + 64;
+    LPWSTR cmdline = (LPWSTR) malloc(cap * sizeof(wchar_t));
+    if (cmdline == NULL) {
+        fwprintf(stderr, L"camel: out of memory\n");
+        return 1;
+    }
+    _snwprintf_s(cmdline, cap, _TRUNCATE,
+                 L"cmd.exe /S /C \"\"%s\\camel.bat\" %s\"", exePath, tail);
+

Review Comment:
   [MEDIUM] **Silent truncation risk**: `_snwprintf_s` with `_TRUNCATE` will silently truncate the formatted string if it exceeds `cap`. While the `+64` margin (the fixed overhead is ~31 chars) makes this practically impossible for realistic paths, checking the return value would guard against silent malformation.
   
   Consider checking the return value:
   ```c
   int written = _snwprintf_s(cmdline, cap, _TRUNCATE,
                L"cmd.exe /S /C \"\"%s\\camel.bat\" %s\"", exePath, tail);
   if (written < 0) {
       fwprintf(stderr, L"camel: command line too long\n");
       free(cmdline);
       return 1;
   }
   ```
   
   _This review was generated by an AI agent and may contain inaccuracies._



##########
tooling/camel-exe/src/main/native/camel.c:
##########
@@ -0,0 +1,106 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * camel.exe - minimal WinGet-compatible bootstrap for the Camel CLI launcher.
+ *
+ * It locates the camel.bat sitting in the same directory, forwards the caller's
+ * exact command-line tail (preserving Unicode and Windows quoting), inherits the
+ * standard streams, and returns the child process exit code. It performs NO Java
+ * discovery and NO Camel option parsing; that all lives in camel.bat.
+ */
+
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <wchar.h>
+
+/* Return the command-line tail after argv[0], preserving the caller's quoting. */
+static LPWSTR skip_argv0(LPWSTR cmd) {
+    LPWSTR p = cmd;
+    if (*p == L'"') {
+        p++;
+        while (*p && *p != L'"') {
+            p++;
+        }
+        if (*p == L'"') {
+            p++;
+        }
+    } else {
+        while (*p && *p != L' ' && *p != L'\t') {
+            p++;
+        }
+    }
+    while (*p == L' ' || *p == L'\t') {
+        p++;
+    }
+    return p;
+}
+
+int wmain(void) {
+    wchar_t exePath[MAX_PATH];
+    DWORD n = GetModuleFileNameW(NULL, exePath, MAX_PATH);

Review Comment:
   [LOW] **MAX_PATH limitation**: On Windows 10+ with long path support enabled (`LongPathsEnabled` registry key), paths can exceed 260 characters. A dynamic allocation loop (doubling the buffer until `GetModuleFileNameW` succeeds with `GetLastError() != ERROR_INSUFFICIENT_BUFFER`) would future-proof this, but it is not a blocker for the initial contribution.
   
   _This review was generated by an AI agent and may contain inaccuracies._



##########
.github/workflows/camel-launcher-windows.yml:
##########
@@ -0,0 +1,127 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+name: Camel launcher Windows build
+
+on:
+  push:
+    branches:
+      - main
+  pull_request:
+    branches:
+      - main
+  workflow_dispatch:
+
+concurrency:
+  group: ${{ github.workflow }}-${{ github.ref }}
+  cancel-in-progress: true
+
+permissions:
+  contents: read
+
+jobs:
+  detect-changes:
+    runs-on: ubuntu-latest
+    outputs:
+      camel-exe: ${{ steps.changes.outputs.camel-exe }}
+      camel-launcher: ${{ steps.changes.outputs.camel-launcher }}
+    steps:
+      - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
+        with:
+          persist-credentials: false
+          fetch-depth: 0
+      - id: changes
+        run: |
+          if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
+            echo "camel-exe=true" >> "$GITHUB_OUTPUT"
+            echo "camel-launcher=true" >> "$GITHUB_OUTPUT"
+            exit 0
+          fi
+
+          if [ "${{ github.event_name }}" = "pull_request" ]; then
+            git fetch origin "${{ github.base_ref }}"
+            CHANGED="$(git diff --name-only "origin/${{ github.base_ref }}"...HEAD)"
+          else
+            CHANGED="$(git diff --name-only "${{ github.event.before }}" "${{ github.sha }}")"
+          fi
+
+          echo "Changed files:"
+          echo "$CHANGED"
+
+          camel_exe=false
+          camel_launcher=false
+
+          if echo "$CHANGED" | grep -qE '^(tooling/camel-exe/|\.github/workflows/camel-launcher-windows\.yml)'; then
+            camel_exe=true
+          fi
+
+          if echo "$CHANGED" | grep -qE '^(dsl/camel-jbang/camel-launcher/|tooling/camel-exe/|\.github/workflows/camel-launcher-windows\.yml)'; then
+            camel_launcher=true
+          fi
+
+          echo "camel-exe=$camel_exe" >> "$GITHUB_OUTPUT"
+          echo "camel-launcher=$camel_launcher" >> "$GITHUB_OUTPUT"
+
+  camel-exe:
+    needs: detect-changes
+    if: github.event_name == 'workflow_dispatch' || needs.detect-changes.outputs.camel-exe == 'true'
+    runs-on: windows-2022
+    steps:
+      - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
+        with:
+          persist-credentials: false
+      - name: Set up JDK 21
+        uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
+        with:
+          distribution: 'temurin'
+          java-version: '21'
+          cache: 'maven'
+      - name: Build and test native camel.exe
+        shell: cmd
+        run: |
+          for /f "usebackq delims=" %%i in (`"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath`) do set "VSINSTALL=%%i"
+          call "%VSINSTALL%\VC\Auxiliary\Build\vcvars64.bat"
+          mvn -B -ntp -pl buildingtools install -DskipTests
+          mvn -B -ntp -pl tooling/camel-exe verify -Dcamel.exe.requireWindowsExe=true
+
+  camel-launcher-windows:
+    needs: detect-changes
+    if: github.event_name == 'workflow_dispatch' || needs.detect-changes.outputs.camel-launcher == 'true'
+    runs-on: windows-2022
+    steps:
+      - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
+        with:
+          persist-credentials: false
+      - name: Set up JDK 21
+        uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
+        with:
+          distribution: 'temurin'
+          java-version: '21'
+          cache: 'maven'
+      - name: Build launcher with native camel.exe and run tests
+        shell: cmd
+        run: |
+          for /f "usebackq delims=" %%i in (`"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath`) do set "VSINSTALL=%%i"
+          call "%VSINSTALL%\VC\Auxiliary\Build\vcvars64.bat"
+          mvn -B -ntp -pl buildingtools,tooling/camel-exe,dsl/camel-jbang/camel-launcher -am install -Dcamel.launcher.requireWindowsExe=true
+      - name: Assert archive carries bin/camel.exe
+        shell: pwsh
+        run: |
+          $zip = Get-ChildItem dsl/camel-jbang/camel-launcher/target/camel-launcher-*-bin.zip | Select-Object -First 1
+          Add-Type -AssemblyName System.IO.Compression.FileSystem
+          $names = [System.IO.Compression.ZipFile]::OpenRead($zip.FullName).Entries.FullName
+          if ($names -notcontains 'bin/camel.exe') { throw 'camel.exe missing from launcher archive' }

Review Comment:
   [INFO] **CI failure note**: The `camel-launcher-windows` job uses `-am` which pulls in the full upstream dependency tree. The current CI failure is in `camel-management` (unrelated to this PR). Consider whether the Maven command here could add `-DskipTests` and rely on the dedicated `camel-exe` job for test execution, plus the PowerShell archive assertion below for distribution validation. This would isolate the launcher build from unrelated test failures in upstream modules.
   
   _This review was generated by an AI agent and may contain inaccuracies._



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] CAMEL-23703: tooling/camel-exe - native camel.exe bootstrap for Windows [camel]

Posted by "ammachado (via GitHub)" <gi...@apache.org>.
ammachado commented on code in PR #24665:
URL: https://github.com/apache/camel/pull/24665#discussion_r3581411831


##########
dsl/camel-jbang/camel-launcher/src/test/java/org/apache/camel/dsl/jbang/launcher/CamelLauncherWindowsExeIT.java:
##########
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.dsl.jbang.launcher;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.stream.Stream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.EnabledIfSystemProperty;
+import org.junit.jupiter.api.condition.EnabledOnOs;
+import org.junit.jupiter.api.condition.OS;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Release gate for the native {@code camel.exe} packaged into the launcher distribution. Runs during {@code verify}
+ * when {@code -Dcamel.launcher.requireWindowsExe=true} is set on a Windows x64 host.
+ */
+@EnabledOnOs(OS.WINDOWS)
+@EnabledIfSystemProperty(named = "camel.launcher.requireWindowsExe", matches = "true")
+class CamelLauncherWindowsExeIT {
+
+    private static final Path TARGET = Paths.get("target");
+    private static final Path STAGED_EXE = TARGET.resolve("camel.exe");
+
+    @Test
+    void stagedCamelExeExists() {
+        assertTrue(Files.isRegularFile(STAGED_EXE),
+                "target/camel.exe must be present before packaging the launcher distribution");
+    }
+
+    @Test
+    void binArchiveIncludesCamelExe() throws IOException {

Review Comment:
   Good catch, same root cause as the CI assertion bug, fixed in f76de4f1c0e3 (suffix match instead of exact `bin/camel.exe` lookup, since `includeBaseDirectory` defaults to `true` in the assembly descriptor).
   
   While digging into this I found a bigger gap worth flagging: the official release pipeline (`Jenkinsfile.deploy`) runs on `ubuntu`, and `build-windows-exe` / `include-camel-exe` only activate via `<os><family>windows</family>`. Neither `camel.exe.requireWindowsExe` nor `camel.launcher.requireWindowsExe` is set anywhere in that pipeline, so on an actual release the native compile is skipped, the `camel.exe` fileSet in `bin.xml` matches nothing, and the released `camel-launcher-*-bin.zip` ships without `camel.exe`, no error, just silently missing. That would break the Winget packaging from the other PR.
   
   @davsclaus since you know the release process better than I do: is there already a place a Windows-hosted build step could hook into (e.g. a separate agent on the release Jenkins job), or should this be a post-release GitHub Actions job that builds the Windows artifact and uploads it alongside the rest of the release? Happy to put a PR together once there's a direction.
   
   _Claude Code on behalf of @ammachado_
   _AI-generated review, so it may get things wrong. Please check any suggestion before you act on it._



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org