Skip to content
Merged
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
1 change: 0 additions & 1 deletion .devcontainer/Dockerfile

This file was deleted.

16 changes: 12 additions & 4 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
{
"name": "PLCNext Dev Container",
"image": "ghcr.io/cyberflaneurx/plc-next-ghcr:latest",
"image": "ghcr.io/adamrodwell/plc-next-ghcr:2024",
"mounts": [
"source=${localEnv:HOME}/.claude,target=/home/plc/.claude,type=bind,consistency=cached"
],
"containerEnv": {
"ANTHROPIC_API_KEY": "${localEnv:ANTHROPIC_API_KEY}"
},
"customizations": {
"vscode": {
"settings": {
Expand Down Expand Up @@ -34,10 +40,12 @@
"aaron-bond.better-comments",
"ms-azuretools.vscode-docker",
"dillonkearns.vscode-gtest-adapter",
"GitHub.vscode-pull-request-github"
"GitHub.vscode-pull-request-github",
"anthropic.claude-code"
]
}
},
"postCreateCommand": "curl -fsSL https://deb.nodesource.com/setup_20.x | sudo bash - && sudo apt-get install -y nodejs && sudo npm install -g @anthropic-ai/claude-code",
"remoteUser": "plc",
"workspaceFolder": "/workspace"
}
"workspaceFolder": "/workspaces/PLCnext"
}
9 changes: 3 additions & 6 deletions .github/workflows/static-code-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,14 @@ jobs:

steps:
- name: Checkout code
uses: actions/checkout@v3

- name: Authenticate Docker with GitHub Container Registry
run: docker login --username cyberflaneurx --password ${{ secrets.GH_PAT }} ghcr.io
uses: actions/checkout@v4

- name: Pull Docker image
run: docker pull ghcr.io/cyberflaneurx/plc-next-ghcr:latest
run: docker pull ghcr.io/adamrodwell/plc-next-ghcr:2024

- name: Start Docker Container
run: |
docker run -d --name plcnext_container -v $(pwd):/code -w /code ghcr.io/cyberflaneurx/plc-next-ghcr:latest sleep infinity
docker run -d --name plcnext_container -v $(pwd):/code -w /code ghcr.io/adamrodwell/plc-next-ghcr:2024 sleep infinity

- name: Ensure Permissions Inside Container
run: |
Expand Down
121 changes: 121 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Environment

This project runs inside a Docker dev container (`ghcr.io/cyberflaneurx/plc-next-ghcr:latest`) using VSCode Dev Containers. All PLCnext CLI tools (`plcncli`) and the cross-compilation SDK are pre-installed in the container. The remote user is `plc`.

The PLCnext SDK targets the **AXCF2152** controller (ARM Cortex-A9, `arm-pxc-linux-gnueabi`) with SDK at `/opt/plcnext_axcf2152_sdk_2023/`. C++ standard is **C++14**.

## Build Commands

All commands are run from within a project directory (e.g., `src/projects/StarterKit`):

```bash
# Generate code and config (required when port definitions change)
export BUILD_TYPE=Release
plcncli generate code --verbose
plcncli generate config --verbose

# Build (cross-compiles for ARM target)
plcncli build --verbose

# Deploy (creates .pcwlx library file in bin/)
plcncli deploy

# Full generate + build + deploy (equivalent to plcnext_gen_build task)
export BUILD_TYPE=Release && plcncli generate code --verbose && plcncli generate config --verbose && plcncli build --verbose && plcncli deploy
```

**Use `plcnext_build` (no generate)** when only `.cpp`/`.hpp` logic changed.
**Use `plcnext_gen_build` (with generate)** when port definitions, component/program metadata annotations, or project structure changed.

## Static Analysis

```bash
# Run cppcheck on all projects
cppcheck --quiet --enable=warning --force --error-exitcode=2 src/projects

# With unusedFunction suppressed (as used in CI)
cppcheck --quiet --enable=warning --force --error-exitcode=2 --suppress=unusedFunction src/projects/StarterKit
```

## Scaffolding New Projects/Components/Programs

```bash
# New project (sets target to AXCF2152 automatically)
cd src/projects && plcncli new project -n <ProjectName> --force
cd <ProjectName> && plcncli set target --add -n AXCF2152

# New component within a project
cd src/projects/<ProjectName> && plcncli new component -n <ComponentName>

# New program within a component
cd src/projects/<ProjectName> && plcncli new program -n <ProgramName> -c <ComponentName>

# After scaffolding, always regenerate
plcncli generate all
```

## Architecture

### PLCnext Component Model (ARP Framework)

Each PLCnext project compiles to a shared library (`.so`) packaged as a `.pcwlx` file for use in PLCnext Engineer.

The ARP (Automation Runtime Platform) framework structures code into three layers:

- **Library** (`*Library.hpp/.cpp`) — auto-generated; registers the library with the runtime. Do not edit manually.
- **Component** (`*Component.hpp/.cpp`) — manages lifecycle (`Initialize`, `LoadConfig`, `SetupConfig`, `ResetConfig`, `PowerDown`) and owns a `ProgramProvider`. Inherits `ComponentBase` and `ProgramComponentBase`.
- **Program** (`*Program.hpp/.cpp`) — contains the cyclic execution logic in `Execute()`. Inherits `ProgramBase`.

The `intermediate/` directory contains auto-generated files (code and config metadata). **Do not manually edit files in `intermediate/`** — they are regenerated by `plcncli generate`.

### Port Annotation System

Ports (I/O variables exposed to the PLCnext GDS/OPC-UA) are declared using comment annotations in header files:

```cpp
//#port
//#attributes(Input|Opc)
//#name(MyPortName)
Arp::boolean myField_;
```

Port attributes: `Input`, `Output`, `Retain`, `Opc`. After changing any port annotations, `plcncli generate code` and `plcncli generate config` must be re-run.

### Project Structure

```
src/projects/<ProjectName>/
├── plcnext.proj # Project metadata (target: AXCF2152)
├── CMakeLists.txt # CMake build; links ArpDevice and ArpProgramming
├── src/ # Hand-written source files (Component, Program headers/impls)
├── intermediate/
│ ├── code/ # Auto-generated: Library, ProgramProvider, *.meta.cpp
│ └── config/ # Auto-generated: .libmeta, .typemeta, .compmeta, .progmeta
└── external/ # Place dependent libraries here
```

### Output Artifact

The built `.pcwlx` file is copied to `/home/plc/Windows_PLCNextEngineer_Libraries` (accessible from the Windows host) for import into PLCnext Engineer.

## Code Style

Formatting is enforced by clang-format-14 with `.clang-format` at the repo root:
- Allman brace style, 4-space indent, 100-column limit
- Pointer alignment: right (`int *ptr`)
- Includes sorted, trailing comments aligned

Format-on-save is configured in the dev container. To format manually: `clang-format-14 -i <file>`.

## CI

GitHub Actions (`.github/workflows/static-code-analysis.yml`) runs on push/PR to `main`:
1. Pulls the dev container image
2. Runs `cppcheck`
3. Runs `plcncli generate code`, `generate config`, `build`, `deploy`

Requires `GH_PAT` secret for authenticating with `ghcr.io`.
10 changes: 10 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
services:
dev:
image: ghcr.io/adamrodwell/plc-next-ghcr:2024
volumes:
- .:/workspace:cached
- ~/.claude:/home/plc/.claude
command: sleep infinity
environment:
- SHELL=/bin/zsh
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:-}
2 changes: 1 addition & 1 deletion src/projects/StarterKit/plcnext.proj
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@
<Name>StarterKit</Name>
<GenerateDTArrayNameByType>true</GenerateDTArrayNameByType>
<GenerateNamespaces>true</GenerateNamespaces>
<Target>AXCF2152,2023.0.0 LTS (23.0.0.65)</Target>
<Target>AXCF2152,24.0.9.199</Target>
</ProjectSettings>
Loading