Resolving SIMATIC IOT2000 HelloWorld Build Missing Executable Fix

David Krause9 min read
Other TopicSiemensTroubleshooting
Licensed PE Working through this on a live machine? A Maine-licensed engineer can take it from here — included with IMD hardware, by the hour for everything else. Book an engineer

Problem Overview

When following the official SIMATIC IOT2000 - Getting Started procedure with Eclipse IDE for C/C++ Developers Neon.2 (4.6.2) and the Siemens-provided Yocto/Poky SDK, the incremental build completes without errors and reports Build Finished (took 6s.565ms), yet the release folder contains only the intermediate object file example.o. The expected final executable HelloWorld is never produced, so the SCP/SFTP transfer dialog described in the Getting Started manual step 4 cannot resolve a valid host path and the OK button stays disabled. This behavior is reproducible on Windows 10 and on Linux guest VMs using the same workspace.

The problem is not in the toolchain itself; the cross-compiler i586-poky-linux-g++ and the --sysroot path resolve correctly. The defect is in the Eclipse CDT build configuration that the Getting Started wizard generates: the compile command retains the GCC stop-after-compile flag in both the global tool settings and the per-file command pattern, and the linker step is configured with the wrong artifact extension.

Symptom summary: Build log shows two compile commands and no link command. Release directory lists only example.o. SCP dialog host path resolves to example.o instead of HelloWorld. OK button greyed out when typing the path manually because the file does not exist.

Affected Environment and SDK Layout

The error reproduces against the canonical Siemens IOT2000 SDK tree. The exact paths used in the failing build are listed below; if your installation differs only by drive letter or username, the same remediation applies.

Component Verified Value
Eclipse package Eclipse IDE for C/C++ Developers, Neon.2 Release (4.6.2), Build id 20161208-0600
Cross-compiler i586-poky-linux-g++
Target architecture -m32 -march=i586
SDK root C:\00_Data\SDK_Destination_Folder\sysroots\i586-nlp-32-poky-linux
C++ headers usr/include/c++/5.3.0 with target tuple i586-poky-linux
mraa library usr/include/mraa, linked with -lmraa
upm library usr/include/upm
Source file ..\example.cpp
Object file example.o
Expected output HelloWorld (no extension)

The SDK is generated by the Yocto Project and provides a self-contained sysroot with the GNU C++ 5.3.0 runtime, the libmraa userspace GPIO/I2C/SPI library and the libupm sensor repository. Reference the official Siemens Industry Online Support portal for the IOT2000 Getting Started entry ID 109741705 and the matching SDK image.

Build Console Analysis

The console output observed during the failing build is reproduced below, normalized for line wrapping. The exact sequence is critical for diagnosis.

20:23:11 **** Incremental Build of configuration IOT2000 Release for project HelloWorld ****
Info: Internal Builder is used for build
i586-poky-linux-g++ "-IC:\00_Data\SDK_Destination_Folder\sysroots\i586-nlp-32-poky-linux\usr\include"
                     "-IC:\00_Data\SDK_Destination_Folder\sysroots\i586-nlp-32-poky-linux\usr\include\c++\5.3.0"
                     "-IC:\00_Data\SDK_Destination_Folder\sysroots\i586-nlp-32-poky-linux\usr\include\c++\5.3.0\i586-poky-linux"
                     "-IC:\00_Data\SDK_Destination_Folder\sysroots\i586-nlp-32-poky-linux\usr\include\mraa"
                     "-IC:\00_Data\SDK_Destination_Folder\sysroots\i586-nlp-32-poky-linux\usr\include\upm"
                     -O0 -g3 -Wall -c -fmessage-length=0 -m32 -march=i586 -c -ffunction-sections -fdata-sections
                     "--sysroot=C:\00_Data\SDK_Destination_Folder\sysroots\i586-nlp-32-poky-linux"
                     -o example.o "..\example.cpp"

i586-poky-linux-g++ -lmraa -fno-use-linker-plugin
                     "--sysroot=C:\00_Data\SDK_Destination_Folder\sysroots\i586-nlp-32-poky-linux"
                     -o HelloWorld example.o

20:23:17 Build Finished (took 6s.565ms)

Notice that the compile invocation contains the flag -c twice and a second -c on the same line. Although GCC tolerates duplicate -c, the second occurrence is a strong indicator that the Getting Started wizard's per-file command pattern was edited and the global C/C++ Build > Settings > GCC C++ Compiler command pattern was left at its default ${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX} ${INPUTS}, which already appends -c. Meanwhile, the linker invocation appears to run correctly. The actual root cause lies in a different setting covered in the next section.

Root Cause: Why example.o Is Produced Without HelloWorld

Three configuration defects, individually or combined, prevent Eclipse CDT's Internal Builder from generating the final executable:

  1. Wrong artifact extension in the linker step. Project Properties > C/C++ Build > Settings > GCC C++ Linker > Output file. The Getting Started template leaves ${OUTPUT_PREFIX}${OUTPUT} in the command pattern but sets the artifact extension to o instead of leaving it blank (or specifying an empty extension). The Internal Builder therefore writes HelloWorld.o, which then collides with the compile artifact name and is either overwritten or skipped.
  2. Per-file compile command pattern overrides the global pattern. Project Properties > C/C++ Build > Settings > GCC C++ Compiler > Command line pattern. If a custom pattern that strips -c is inserted here, the Internal Builder treats every translation unit as a link candidate and never finalizes an executable.
  3. Missing linker step on the build invocation. Project Properties > C/C++ Build > Tool Chain Editor. The "Current toolchain" must be "Cross GCC". If the wizard accidentally selected "No Toolchain" the link step is suppressed entirely.
Why example.o remains in the folder: The C++ compile step writes example.o from example.cpp. When the linker step fails silently (because the artifact extension is o and it tries to overwrite the object file with itself, or because the command pattern is missing -o ${OUTPUT}), the object file is the only persistent artifact. Project -> Clean -> Clean all removes it, but the next incremental build reproduces the same problem because the configuration is unchanged.

Diagnosis Procedure

Confirm each defect before applying the fix:

  1. In Eclipse, right-click the HelloWorld project and select Properties.
  2. Navigate to C/C++ Build > Tool Chain Editor. Confirm Current toolchain is Cross GCC and Current builder is Gnu Make Builder or CDT Internal Builder with the toolchain fields populated.
  3. Open C/C++ Build > Settings > Cross Settings. Confirm Prefix is i586-poky-linux- and Path points to the Yocto SDK environment script directory (typically C:\00_Data\SDK_Destination_Folder\sysroots\i586-nlp-32-poky-linux\usr\bin\..\..\environment-setup-i586-nlp-32-poky-linux on Windows).
  4. Open C/C++ Build > Settings > GCC C++ Compiler. Inspect the Command line pattern field. It must read exactly:
    ${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX} ${INPUTS}
  5. Open C/C++ Build > Settings > GCC C++ Linker. Inspect Command line pattern (should be ${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX} ${INPUTS}) and Output file (should be ${OUTPUT_PREFIX}${OUTPUT} with extension blank).
  6. Click Project > Clean..., enable Clean all projects, click OK, then Project > Build Project. Repeat the console inspection.

Solution A: Correct the Cross-Compiler Command Pattern

The duplicate -c in the console output shows that an additional flag string was injected into the command pattern. Reset it:

  1. Project Properties > C/C++ Build > Settings > Cross Settings > Command: set to g++.
  2. Project Properties > C/C++ Build > Settings > GCC C++ Compiler: set the Command line pattern to:
    ${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX} ${INPUTS}
  3. Project Properties > C/C++ Build > Settings > GCC C++ Compiler > Miscellaneous: clear the Other flags field if it contains stray -c, -shared, or -fPIC entries not required by the HelloWorld example.
  4. Click Apply and Close.

Solution B: Configure Linker Output Artifact

This is the most common fix for the symptom where only example.o remains in the release folder.

  1. Project Properties > C/C++ Build > Settings > GCC C++ Linker.
  2. In Expert settings, click Output file. Replace the existing value with:
    ${OUTPUT_PREFIX}${OUTPUT}
  3. Confirm the Command line pattern field reads:
    ${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX} ${INPUTS}
  4. Still under GCC C++ Linker > Libraries, add mraa to Libraries (-l). The Getting Started template sets this via -lmraa; if the linker output command line shows no -l tokens, add the library here instead of via Other flags.
  5. Open the GCC C++ Linker > Miscellaneous subnode and ensure the Linker flags field contains -fno-use-linker-plugin only if required by the Yocto toolchain version in use; remove duplicate --sysroot entries.

Solution C: Force Full Rebuild After Clean

If Solutions A and B are in place but the executable still does not appear, force the Internal Builder to relink by removing every intermediate artifact:

  1. Close Eclipse.
  2. In Windows Explorer, navigate to the workspace folder (typically C:\Users\<user>\workspace\HelloWorld).
  3. Delete the entire IOT2000 Release subfolder and any sibling IOT2000 Debug folder.
  4. Reopen Eclipse, right-click the project, and select Project > Build Project (do not use Build All; on Neon.2 CDT this can re-trigger incremental caching).
  5. Inspect the console. The expected sequence is now exactly two lines: one compile invocation, one link invocation.

Deploying HelloWorld to the SIMATIC IOT2000

Once the release folder contains the executable HelloWorld, proceed with the deployment step from the Getting Started manual:

  1. In the Eclipse Remote Systems Explorer (RSE) perspective, expand the SIMATIC IOT2000 node and connect via SSH.
  2. Right-click My Home (or the target folder such as /home/iot/) and select Upload Files....
  3. In the host field, browse to C:\Users\<user>\workspace\HelloWorld\IOT2000 Release\HelloWorld and confirm the OK button activates.
  4. On the target, open a serial console or SSH session and execute:
    chmod +x /home/iot/HelloWorld
    /home/iot/HelloWorld
Permission reminder: The Yocto rootfs on IOT2000 sets noexec on /tmp. Do not upload the executable there; the binary will load but will refuse to execute with Permission denied. Use /home/iot or /opt instead.

Verification Checklist

Step Expected Result
Release folder contents example.o AND HelloWorld present, no other ELF artifacts.
Console build duration Single compile line, single link line, total time < 15 s on a modern workstation.
Linker command line Contains exactly one -o token followed by HelloWorld (no extension).
Upload dialog OK button enables immediately when the executable path is selected.
SSH execution Program prints Hello, world! (or equivalent output of example.cpp) and returns exit code 0.
Clean rebuild After Project -> Clean -> Clean all the next Build Project reproduces both artifacts in < 15 s.

Troubleshooting Matrix

Observed Symptom Likely Cause Corrective Action
Only example.o in release folder Linker output extension set to o Solution B: blank the extension field
Compile command line shows two -c flags Custom command pattern injected Solution A: restore default pattern
Build completes in < 1 s with no compile output Toolchain set to No Toolchain Project Properties > Tool Chain Editor > select Cross GCC
Linker error: cannot find -lmraa SDK sysroot not in linker search path Add -L${SYSROOT}/usr/lib to linker flags
Upload OK button greyed out Path typed manually instead of browsed, and file does not exist Browse to IOT2000 Release, confirm HelloWorld (no extension) is listed
Permission denied on target Executable copied to /tmp or not chmodded Move to /home/iot and run chmod +x
GLIBC version mismatch on target SDK glibc newer than rootfs glibc Match SDK image to firmware version per Siemens KB 109755230
Linker produces HelloWorld.o Output extension field still contains o Edit Output file to ${OUTPUT_PREFIX}${OUTPUT} with empty extension

FAQ

Why does the SIMATIC IOT2000 Eclipse build create example.o but not HelloWorld?

Eclipse CDT's Internal Builder produces the final executable in the linker step. If the linker output extension is incorrectly set to o, or if the toolchain is set to No Toolchain, the build stops after compilation and only the intermediate object file example.o remains. Verify Project Properties > C/C++ Build > Settings > GCC C++ Linker > Output file = ${OUTPUT_PREFIX}${OUTPUT} with an empty extension.

What does the duplicate -c flag in the build command mean?

A second -c on the GCC command line indicates the command pattern in Project Properties > C/C++ Build > Settings > GCC C++ Compiler was edited to include stop-after-compile flags while the default pattern already provides them. Reset the Command line pattern to ${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX} ${INPUTS} and clear any stray flags in the Miscellaneous > Other flags field.

How do I deploy the HelloWorld binary from Eclipse to the SIMATIC IOT2000?

Use the Remote Systems Explorer perspective, connect to the IOT2000 over SSH, right-click the target folder (/home/iot), and select Upload Files. Browse the host path to <workspace>\HelloWorld\IOT2000 Release\HelloWorld, not example.o. On the target, run chmod +x /home/iot/HelloWorld followed by /home/iot/HelloWorld.

Which Eclipse version does the SIMATIC IOT2000 Getting Started manual target?

The published Getting Started entry on Siemens Industry Online Support targets Eclipse IDE for C/C++ Developers Neon.2 (4.6.2), Build id 20161208-0600, paired with the Yocto/Poky i586 SDK containing GCC 5.3.0 and libmraa 1.0.x. Newer Eclipse versions require manually remapping the toolchain paths and tool IDs because the CDT schema changed in Oxygen and later releases.

Why does Project > Clean all followed by Build all not regenerate HelloWorld?

Clean only removes generated artifacts; it does not reset the toolchain configuration. If the linker output extension is still o, the next build reproduces the same defect. After fixing Solutions A and B, perform a manual delete of the IOT2000 Release folder before rebuilding to force the Internal Builder to regenerate the executable.

Back to blog