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
2 changes: 1 addition & 1 deletion .github/workflows/self_hosted_build_and_test.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: Self-Hosted Build and Test

on:
push:
pull_request:
branches: [ develop ]
workflow_dispatch:
inputs:
Expand Down
171 changes: 171 additions & 0 deletions .github/workflows/self_hosted_decent_ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
name: Self-Hosted Decent CI

on:
pull_request:
branches: [ develop ]

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
cancel-in-progress: true

env:
BUILD_DIR: build-decent-ci
Python_REQUIRED_VERSION: "3.12.2"

jobs:
build_and_test:
name: GCC 13.3 build and split tests
if: >-
${{
github.event.pull_request.head.repo.full_name == github.repository &&
github.event.pull_request.head.repo.fork == false
}}
runs-on: [ self-hosted, linux, x64, ubuntu-24.04 ]

steps:
- name: Checkout EnergyPlus
uses: actions/checkout@v6
with:
ref: ${{ github.event.pull_request.head.sha }}
persist-credentials: false

- name: Setup runner
id: setup-runner
uses: ./.github/actions/setup-runner
with:
python-version: ${{ env.Python_REQUIRED_VERSION }}
python-arch: x64

- name: Select GCC 13.3 toolchain
id: compiler
shell: bash
run: |
sudo apt-get -qq update
sudo apt-get -qq install -y gcc-13 g++-13 gfortran-13

gcc_version="$(gcc-13 -dumpfullversion -dumpversion)"
case "$gcc_version" in
13.3*) ;;
*)
echo "::error::Expected GCC 13.3.x, found ${gcc_version}"
exit 1
;;
esac

{
echo "CC=$(command -v gcc-13)"
echo "CXX=$(command -v g++-13)"
echo "FC=$(command -v gfortran-13)"
} >> "$GITHUB_ENV"
echo "compiler-id=gcc-${gcc_version}" >> "$GITHUB_OUTPUT"
gcc-13 --version
g++-13 --version
gfortran-13 --version

- name: Restore ccache
id: cacheccache-restore
uses: actions/cache/restore@v5
with:
path: |
${{ steps.setup-runner.outputs.ccache-dir }}
key: ccache-self-hosted-decent-ci-${{ runner.os }}-${{ steps.compiler.outputs.compiler-id }}-pr-${{ github.event.pull_request.number }}

- name: Show restored ccache state
shell: bash
run: |
begin_group() { echo -e "::group::\033[93m$1\033[0m"; }

if [ "${{ steps.cacheccache-restore.outputs.cache-hit }}" = "true" ]; then
echo "CCache primary key was hit"
else
echo "No exact ccache hit"
fi

begin_group "Existing ccache stats"
ccache --show-stats -vv || ccache --show-stats
echo "::endgroup::"

ccache --zero-stats
begin_group "CCache config"
ccache -p
echo "::endgroup::"

- name: Configure build
shell: bash
run: |
cmake -S . -B "$BUILD_DIR" \
-G Ninja \
-DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo \
-DCMAKE_C_COMPILER:FILEPATH="$CC" \
-DCMAKE_CXX_COMPILER:FILEPATH="$CXX" \
-DCMAKE_Fortran_COMPILER:FILEPATH="$FC" \
-DLINK_WITH_PYTHON:BOOL=ON \
-DPYTHON_CLI:BOOL=OFF \
-DPython_REQUIRED_VERSION:STRING="$Python_REQUIRED_VERSION" \
-DPython_ROOT_DIR:PATH="${{ steps.setup-runner.outputs.python-root-dir }}" \
-DPython_EXECUTABLE:FILEPATH="${{ steps.setup-runner.outputs.python-executable }}" \
-DBUILD_FORTRAN:BOOL=ON \
-DBUILD_TESTING:BOOL=ON \
-DENABLE_REGRESSION_TESTING:BOOL=OFF \
-DCOMMIT_SHA:STRING="${{ github.event.pull_request.head.sha }}" \
-DENABLE_GTEST_DEBUG_MODE:BOOL=OFF \
-DENABLE_PCH:BOOL=OFF \
-DFORCE_DEBUG_ARITHM_GCC_OR_CLANG:BOOL=ON \
-DBUILD_PACKAGE:BOOL=OFF \
-DDOCUMENTATION_BUILD:STRING=DoNotBuild

- name: Build
shell: bash
run: |
echo "::add-matcher::./.github/workflows/cpp-problem-matcher.json"
cmake --build "$BUILD_DIR" -j "${NPROC:-$(nproc)}"
echo "::remove-matcher owner=gcc-problem-matcher::"

- name: Show build ccache stats
if: always()
shell: bash
run: |
ccache --show-stats -vv || ccache --show-stats

- name: Save ccache
if: always() && steps.cacheccache-restore.outputs.cache-hit != 'true'
uses: actions/cache/save@v5
with:
path: |
${{ steps.setup-runner.outputs.ccache-dir }}
key: ${{ steps.cacheccache-restore.outputs.cache-primary-key }}

- name: Run unit tests
working-directory: ${{ env.BUILD_DIR }}
shell: bash
run: |
begin_group() { echo -e "::group::\033[93m$1\033[0m"; }

begin_group "Running non-integration CTests"
if ctest -j "${NPROC:-$(nproc)}" --output-on-failure -E "integration.*"; then
echo "::endgroup::"
else
echo "::endgroup::"
begin_group "Re-running failed non-integration tests verbosely"
ctest --rerun-failed -VV
echo "::endgroup::"
fi

- name: Run integration tests
working-directory: ${{ env.BUILD_DIR }}
shell: bash
run: |
begin_group() { echo -e "::group::\033[93m$1\033[0m"; }

begin_group "Running integration CTests"
if ctest -j "${NPROC:-$(nproc)}" --output-on-failure -R "integration.*"; then
echo "::endgroup::"
else
echo "::endgroup::"
begin_group "Re-running failed integration tests verbosely"
ctest --rerun-failed -VV
echo "::endgroup::"
fi
2 changes: 1 addition & 1 deletion .github/workflows/test_develop_commits.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
# pretty: "Standard Build on Mac x64"
# alternate: false
- os: macos-14
macos_dev_target: 13.0
macos_dev_target: 14.0
arch: arm64
python-arch: arm64
generator: "Unix Makefiles"
Expand Down
33 changes: 19 additions & 14 deletions src/EnergyPlus/api/datatransfer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@

// C++ Headers
#include <cmath>
#include <format>
#include <cstdlib>
#include <cstring>

// ObjexxFCL Headers
#include <ObjexxFCL/ArrayS.functions.hh>
Expand All @@ -72,6 +73,20 @@

using namespace EnergyPlus;

namespace {

char *copyStringForAPI(std::string const &value)
{
auto *result = static_cast<char *>(std::malloc(value.size() + 1));
if (result == nullptr) {
return nullptr;
}
std::memcpy(result, value.c_str(), value.size() + 1);
return result;
}

} // namespace

APIDataEntry *getAPIData(EnergyPlusState state, unsigned int *resultingSize)
{
struct LocalAPIDataEntry
Expand Down Expand Up @@ -218,13 +233,7 @@ char *listAllAPIDataCSV(EnergyPlusState state)
? variable->unitNameCustomEMS
: EnergyPlus::Constant::unitNames[(int)variable->units]));
}
// note that we cannot just return a c_str to the local string, as the string will be destructed upon leaving
// this function, and undefined behavior will occur.
// instead make a deep copy, and the user must manage the new char * pointer
// strcpy copies including the null-terminator, strlen doesn't include it
char *p = new char[std::strlen(output.c_str()) + 1];
std::strcpy(p, output.c_str());
return p;
return copyStringForAPI(output);
}

int apiDataFullyReady(EnergyPlusState state)
Expand Down Expand Up @@ -255,18 +264,14 @@ char *inputFilePath(EnergyPlusState state)
{
const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
std::string const path_utf8 = EnergyPlus::FileSystem::toGenericString(thisState->dataStrGlobals->inputFilePath);
char *p = new char[std::strlen(path_utf8.c_str()) + 1];
std::strcpy(p, path_utf8.c_str());
return p;
return copyStringForAPI(path_utf8);
}

char *epwFilePath(EnergyPlusState state)
{
const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
std::string const path_utf8 = EnergyPlus::FileSystem::toGenericString(thisState->files.inputWeatherFilePath.filePath);
char *p = new char[std::strlen(path_utf8.c_str()) + 1];
std::strcpy(p, path_utf8.c_str());
return p;
return copyStringForAPI(path_utf8);
}

char **getObjectNames(EnergyPlusState state, const char *objectType, unsigned int *resultingSize)
Expand Down
Loading