Compare commits

..

2 Commits

Author SHA1 Message Date
2cdf56f8d6 ide: the whole project in Solution Explorer, and a path Studio can resolve
Three things the solution got wrong, all found by opening it in the GUI rather
than building it headlessly.

The project listed only main.cpp, so none of the headers could be opened from
Solution Explorer. Every source and header is listed now, with <Link> mirroring
the on-disk src/ layout, which is what master's project did.

Neither configuration compiled in the GUI: libavr was found through
$(LIBAVR_ROOT), and a variable exported in a shell is not visible to Studio
launched from the Start menu. Release only looked healthy because its objects
were already up to date from a headless build. The path is now anchored to the
project directory, which also side-steps a second trap: a plain relative include
is resolved against the generated makefile's own directory, the configuration's
output directory, not the project's. Pinning libavr as a submodule would remove
the assumption that the two sit side by side, and is on libavr's task list.

Both configurations verified with LIBAVR_ROOT deliberately unset, Release still
byte-identical to the CMake build and the flag gate still green. Debug's own
translation unit carries DWARF-4 as intended.

Studio's per-user state under ide/.vs/ and the build logs are ignored.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-27 19:19:20 +02:00
00849d25d5 ide: the Atmel Studio solution master has, on the libavr port
master opens in Studio, so this branch should too. One project, the port's own
chip, flags mirrored by hand against the CMake build — and the acceptance is
not that it builds but that it builds the same firmware: .text (7094 B) and
.data (336 B) come out byte-identical to the CMake output from the same
sources.

libavr is found through $(LIBAVR_ROOT), the variable the CMake build already
uses, so no machine path is committed; Studio expands it from the environment.
The toolchain is named by flavour only, since nothing Studio ships can compile
-std=c++26 and the path to one that can is per-machine state.

The componentinfo file the project cannot load without is generated by
libavr's tools/atmelstudio/componentinfo.py and ignored here, as are Studio's
output directories. Release is what the flag gate compares, the presets
defining no debug build; Debug carries the -Og -gdwarf-4 pair libavr's own
debug preset uses.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-27 18:37:56 +02:00
4 changed files with 204 additions and 0 deletions

7
.gitignore vendored
View File

@@ -1,2 +1,9 @@
build/ build/
.cache/ .cache/
# Atmel Studio: generated per machine, and its build outputs
ide/*.componentinfo.xml
ide/Debug/
ide/Release/
ide/.vs/
ide/*.log

View File

@@ -19,4 +19,39 @@ LIBAVR_ROOT=/path/to/libavr cmake --preset atmega328p-generated
cmake --build --preset atmega328p-generated cmake --build --preset atmega328p-generated
``` ```
## Atmel Studio
`master` carries a Studio solution, so this branch does too: `ide/fantemp.atsln`
builds the same firmware — byte-identical `.text` and `.data` to the CMake
build — from the same sources, with the flags mirrored by hand.
Studio expects libavr checked out **beside this repo**, and finds it at
`$(MSBuildProjectDirectory)\..\..\libavr\include` — anchored to the project
rather than written relative to the generated makefile, which runs from the
configuration's output directory and would need a different number of `..`.
Unlike the CMake build there is no `LIBAVR_ROOT` to point elsewhere: an
environment variable set in a shell is not visible to Studio launched from the
Start menu, which fails as a missing `libavr/libavr.hpp` rather than as anything
about the variable. Pinning libavr as a submodule is the better answer and is on
libavr's task list.
It also needs a GCC 16.1 toolchain registered as flavour `avr-g++-16.1.0`;
nothing older can compile `-std=c++26`.
One generated file is required before the project will load, and one command
checks the flags have not drifted (both from libavr's `tools/atmelstudio/`):
```sh
python ../libavr/tools/atmelstudio/componentinfo.py \
ide/fantemp.componentinfo.xml --device ATmega328P
python ../libavr/tools/atmelstudio/check-flags.py --solution ide/fantemp.atsln \
--compile-commands build/atmega328p-generated/compile_commands.json \
--log build/atmelstudio.log
```
CMake remains the build system; the solution is there so the project opens in
Studio as its predecessor did. Only the Release configuration is gated against
CMake — the presets define no debug build — and Debug carries the `-Og
-gdwarf-4` pair libavr's own debug preset uses.
Legacy (yazoalfa submodules) stays on `master`. Legacy (yazoalfa submodules) stays on `master`.

22
ide/fantemp.atsln Normal file
View File

@@ -0,0 +1,22 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Atmel Studio Solution File, Format Version 11.00
VisualStudioVersion = 14.0.23107.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{E66E83B9-2572-4076-B26E-6BE79FF3018A}") = "fantemp", "fantemp.cppproj", "{4F0C1D92-6A5B-4E33-9A71-2C8F5B0D47AE}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|AVR = Debug|AVR
Release|AVR = Release|AVR
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{4F0C1D92-6A5B-4E33-9A71-2C8F5B0D47AE}.Debug|AVR.ActiveCfg = Debug|AVR
{4F0C1D92-6A5B-4E33-9A71-2C8F5B0D47AE}.Debug|AVR.Build.0 = Debug|AVR
{4F0C1D92-6A5B-4E33-9A71-2C8F5B0D47AE}.Release|AVR.ActiveCfg = Release|AVR
{4F0C1D92-6A5B-4E33-9A71-2C8F5B0D47AE}.Release|AVR.Build.0 = Release|AVR
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

140
ide/fantemp.cppproj Normal file
View File

@@ -0,0 +1,140 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="14.0">
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
<ProjectVersion>7.0</ProjectVersion>
<ToolchainName>com.Atmel.AVRGCC8.CPP</ToolchainName>
<ProjectGuid>4f0c1d92-6a5b-4e33-9a71-2c8f5b0d47ae</ProjectGuid>
<avrdevice>ATmega328P</avrdevice>
<avrdeviceseries>none</avrdeviceseries>
<OutputType>Executable</OutputType>
<Language>CPP</Language>
<OutputFileName>$(MSBuildProjectName)</OutputFileName>
<OutputFileExtension>.elf</OutputFileExtension>
<OutputDirectory>$(MSBuildProjectDirectory)\$(Configuration)</OutputDirectory>
<AssemblyName>fantemp</AssemblyName>
<Name>fantemp</Name>
<RootNamespace>fantemp</RootNamespace>
<ToolchainFlavour>avr-g++-16.1.0</ToolchainFlavour>
<KeepTimersRunning>true</KeepTimersRunning>
<OverrideVtor>false</OverrideVtor>
<CacheFlash>true</CacheFlash>
<ProgFlashFromRam>true</ProgFlashFromRam>
<RamSnippetAddress>0x20000000</RamSnippetAddress>
<UncachedRange />
<preserveEEPROM>true</preserveEEPROM>
<OverrideVtorValue>exception_table</OverrideVtorValue>
<BootSegment>2</BootSegment>
<ResetRule>0</ResetRule>
<eraseonlaunchrule>0</eraseonlaunchrule>
<EraseKey />
<AsfFrameworkConfig>
<framework-data xmlns="">
<options />
<configurations />
<files />
<documentation help="" />
<offline-documentation help="" />
<dependencies>
<content-extension eid="atmel.asf" uuidref="Atmel.ASF" version="3.52.0" />
</dependencies>
</framework-data>
</AsfFrameworkConfig>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<ToolchainSettings>
<AvrGccCpp>
<avrgcc.common.Device>-mmcu=atmega328p</avrgcc.common.Device>
<avrgcc.common.outputfiles.hex>True</avrgcc.common.outputfiles.hex>
<avrgcc.common.outputfiles.lss>True</avrgcc.common.outputfiles.lss>
<avrgcc.common.outputfiles.eep>True</avrgcc.common.outputfiles.eep>
<avrgcc.common.outputfiles.srec>True</avrgcc.common.outputfiles.srec>
<avrgcc.common.outputfiles.usersignatures>False</avrgcc.common.outputfiles.usersignatures>
<avrgcccpp.compiler.symbols.DefSymbols>
<ListValues>
<Value>NDEBUG</Value>
</ListValues>
</avrgcccpp.compiler.symbols.DefSymbols>
<avrgcccpp.compiler.directories.IncludePaths>
<ListValues>
<Value>$(MSBuildProjectDirectory)\..\..\libavr\include</Value>
</ListValues>
</avrgcccpp.compiler.directories.IncludePaths>
<avrgcccpp.compiler.optimization.level>Optimize for size (-Os)</avrgcccpp.compiler.optimization.level>
<avrgcccpp.compiler.optimization.PrepareFunctionsForGarbageCollection>True</avrgcccpp.compiler.optimization.PrepareFunctionsForGarbageCollection>
<avrgcccpp.compiler.optimization.PrepareDataForGarbageCollection>True</avrgcccpp.compiler.optimization.PrepareDataForGarbageCollection>
<avrgcccpp.compiler.warnings.AllWarnings>True</avrgcccpp.compiler.warnings.AllWarnings>
<avrgcccpp.compiler.miscellaneous.OtherFlags>-std=c++26 -Wextra -mrelax -fno-exceptions -fno-rtti -fno-threadsafe-statics</avrgcccpp.compiler.miscellaneous.OtherFlags>
<avrgcccpp.linker.optimization.GarbageCollectUnusedSections>True</avrgcccpp.linker.optimization.GarbageCollectUnusedSections>
<avrgcccpp.linker.miscellaneous.LinkerFlags>-mrelax</avrgcccpp.linker.miscellaneous.LinkerFlags>
</AvrGccCpp>
</ToolchainSettings>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<ToolchainSettings>
<AvrGccCpp>
<avrgcc.common.Device>-mmcu=atmega328p</avrgcc.common.Device>
<avrgcc.common.outputfiles.hex>True</avrgcc.common.outputfiles.hex>
<avrgcc.common.outputfiles.lss>True</avrgcc.common.outputfiles.lss>
<avrgcc.common.outputfiles.eep>True</avrgcc.common.outputfiles.eep>
<avrgcc.common.outputfiles.srec>True</avrgcc.common.outputfiles.srec>
<avrgcc.common.outputfiles.usersignatures>False</avrgcc.common.outputfiles.usersignatures>
<avrgcccpp.compiler.symbols.DefSymbols>
<ListValues>
<Value>DEBUG</Value>
</ListValues>
</avrgcccpp.compiler.symbols.DefSymbols>
<avrgcccpp.compiler.directories.IncludePaths>
<ListValues>
<Value>$(MSBuildProjectDirectory)\..\..\libavr\include</Value>
</ListValues>
</avrgcccpp.compiler.directories.IncludePaths>
<avrgcccpp.compiler.optimization.level>Optimize debugging experience (-Og)</avrgcccpp.compiler.optimization.level>
<avrgcccpp.compiler.optimization.PrepareFunctionsForGarbageCollection>True</avrgcccpp.compiler.optimization.PrepareFunctionsForGarbageCollection>
<avrgcccpp.compiler.optimization.PrepareDataForGarbageCollection>True</avrgcccpp.compiler.optimization.PrepareDataForGarbageCollection>
<avrgcccpp.compiler.warnings.AllWarnings>True</avrgcccpp.compiler.warnings.AllWarnings>
<avrgcccpp.compiler.miscellaneous.OtherFlags>-std=c++26 -Wextra -mrelax -fno-exceptions -fno-rtti -fno-threadsafe-statics -gdwarf-4</avrgcccpp.compiler.miscellaneous.OtherFlags>
<avrgcccpp.linker.optimization.GarbageCollectUnusedSections>True</avrgcccpp.linker.optimization.GarbageCollectUnusedSections>
<avrgcccpp.linker.miscellaneous.LinkerFlags>-mrelax</avrgcccpp.linker.miscellaneous.LinkerFlags>
</AvrGccCpp>
</ToolchainSettings>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\src\board.hpp">
<SubType>compile</SubType>
<Link>src\board.hpp</Link>
</Compile>
<Compile Include="..\src\bootloader.hpp">
<SubType>compile</SubType>
<Link>src\bootloader.hpp</Link>
</Compile>
<Compile Include="..\src\controller.hpp">
<SubType>compile</SubType>
<Link>src\controller.hpp</Link>
</Compile>
<Compile Include="..\src\curve.hpp">
<SubType>compile</SubType>
<Link>src\curve.hpp</Link>
</Compile>
<Compile Include="..\src\main.cpp">
<SubType>compile</SubType>
<Link>src\main.cpp</Link>
</Compile>
<Compile Include="..\src\statistics.hpp">
<SubType>compile</SubType>
<Link>src\statistics.hpp</Link>
</Compile>
<Compile Include="..\src\terminal.hpp">
<SubType>compile</SubType>
<Link>src\terminal.hpp</Link>
</Compile>
<Compile Include="..\src\thermistor.hpp">
<SubType>compile</SubType>
<Link>src\thermistor.hpp</Link>
</Compile>
</ItemGroup>
<ItemGroup>
<Folder Include="src" />
</ItemGroup>
<Import Project="$(AVRSTUDIO_EXE_PATH)\Vs\Compiler.targets" />
</Project>