diff --git a/arduino/cores/cores.go b/arduino/cores/cores.go
index 69669efff4b..aa6886d9948 100644
--- a/arduino/cores/cores.go
+++ b/arduino/cores/cores.go
@@ -337,6 +337,7 @@ func (release *PlatformRelease) RuntimeProperties() *properties.Map {
 	res := properties.NewMap()
 	if release.InstallDir != nil {
 		res.Set("runtime.platform.path", release.InstallDir.String())
+		res.Set("runtime.hardware.path", release.InstallDir.Join("..").String())
 	}
 
 	return res
diff --git a/internal/integrationtest/compile_2/compile_propeties_test.go b/internal/integrationtest/compile_2/compile_propeties_test.go
new file mode 100644
index 00000000000..c636bc16f82
--- /dev/null
+++ b/internal/integrationtest/compile_2/compile_propeties_test.go
@@ -0,0 +1,54 @@
+// This file is part of arduino-cli.
+//
+// Copyright 2022 ARDUINO SA (http://www.arduino.cc/)
+//
+// This software is released under the GNU General Public License version 3,
+// which covers the main part of arduino-cli.
+// The terms of this license can be found at:
+// https://www.gnu.org/licenses/gpl-3.0.en.html
+//
+// You can be released from the requirements of the above licenses by purchasing
+// a commercial license. Buying such a license is mandatory if you want to
+// modify or otherwise use the software for commercial activities involving the
+// Arduino software without disclosing the source code of your own applications.
+// To purchase a commercial license, send an email to license@arduino.cc.
+
+package compile_test
+
+import (
+	"testing"
+
+	"github.com/arduino/arduino-cli/internal/integrationtest"
+	"github.com/arduino/go-paths-helper"
+	"github.com/stretchr/testify/require"
+)
+
+func TestCompileAndUploadRuntimeProperties(t *testing.T) {
+	env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
+	defer env.CleanUp()
+
+	// https://github.com/arduino/arduino-cli/issues/1971
+	sketchbookHardwareDir := cli.SketchbookDir().Join("hardware")
+	require.NoError(t, sketchbookHardwareDir.MkdirAll())
+
+	// Copy test platform
+	testPlatform := paths.New("..", "testdata", "foo")
+	require.NoError(t, testPlatform.CopyDirTo(sketchbookHardwareDir.Join("foo")))
+
+	// Install dependencies of the demo platform
+	_, _, err := cli.Run("core", "update-index")
+	require.NoError(t, err)
+	_, _, err = cli.Run("core", "install", "arduino:avr")
+	require.NoError(t, err)
+
+	// Check compile runtime propeties expansion
+	bareMinimum := cli.CopySketch("bare_minimum")
+	stdout, _, err := cli.Run("compile", "--fqbn", "foo:avr:bar", "-v", bareMinimum.String())
+	require.NoError(t, err)
+	require.Contains(t, string(stdout), "PREBUILD-runtime.hardware.path="+sketchbookHardwareDir.String())
+
+	// Check upload runtime propeties expansion
+	stdout, _, err = cli.Run("upload", "--fqbn", "foo:avr:bar", bareMinimum.String())
+	require.NoError(t, err)
+	require.Contains(t, string(stdout), "UPLOAD-runtime.hardware.path="+sketchbookHardwareDir.String())
+}
diff --git a/internal/integrationtest/testdata/bare_minimum/bare_minimum.ino b/internal/integrationtest/testdata/bare_minimum/bare_minimum.ino
new file mode 100644
index 00000000000..660bdbccfdb
--- /dev/null
+++ b/internal/integrationtest/testdata/bare_minimum/bare_minimum.ino
@@ -0,0 +1,2 @@
+void setup() {}
+void loop() {}
diff --git a/internal/integrationtest/testdata/foo/avr/boards.txt b/internal/integrationtest/testdata/foo/avr/boards.txt
new file mode 100644
index 00000000000..fd334f7dbff
--- /dev/null
+++ b/internal/integrationtest/testdata/foo/avr/boards.txt
@@ -0,0 +1,8 @@
+bar.name=Bar
+bar.upload.tool=baz
+bar.upload.protocol=
+bar.build.board=AVR_BAR
+bar.build.f_cpu=16000000L
+bar.build.mcu=atmega328p
+bar.build.core=arduino:arduino
+bar.build.variant=arduino:standard
diff --git a/internal/integrationtest/testdata/foo/avr/platform.txt b/internal/integrationtest/testdata/foo/avr/platform.txt
new file mode 100644
index 00000000000..119f231af26
--- /dev/null
+++ b/internal/integrationtest/testdata/foo/avr/platform.txt
@@ -0,0 +1,10 @@
+name=Foo Platform
+version=0.0.0
+
+recipe.hooks.prebuild.0.pattern=echo PREBUILD-runtime.hardware.path={runtime.hardware.path}
+recipe.hooks.prebuild.0.pattern.windows=cmd /C echo PREBUILD-runtime.hardware.path={runtime.hardware.path}
+
+tools.baz.upload.params.quiet=
+tools.baz.upload.params.verbose=
+tools.baz.upload.pattern=echo UPLOAD-runtime.hardware.path={runtime.hardware.path}
+tools.baz.upload.pattern.windows=cmd /C echo UPLOAD-runtime.hardware.path={runtime.hardware.path}