diff --git a/api/sixtyfps-cpp/CMakeLists.txt b/api/sixtyfps-cpp/CMakeLists.txt index 436a52344..ce5fb5e1e 100644 --- a/api/sixtyfps-cpp/CMakeLists.txt +++ b/api/sixtyfps-cpp/CMakeLists.txt @@ -136,6 +136,9 @@ if(BUILD_TESTING) add_executable(api_tests tests/tests.cpp) target_link_libraries(api_tests PRIVATE SixtyFPS Catch2::Catch2) + target_compile_definitions(api_tests PRIVATE + SOURCE_DIR=\"${CMAKE_CURRENT_SOURCE_DIR}/\" + ) add_test(api_tests ${CMAKE_CURRENT_BINARY_DIR}/api_tests) # Somehow the wrong relative rpath ends up in the binary, requiring us to change the # working directory. diff --git a/api/sixtyfps-cpp/include/sixtyfps_interpreter.h b/api/sixtyfps-cpp/include/sixtyfps_interpreter.h index 2e5ff9a5a..6707a5a54 100644 --- a/api/sixtyfps-cpp/include/sixtyfps_interpreter.h +++ b/api/sixtyfps-cpp/include/sixtyfps_interpreter.h @@ -502,6 +502,18 @@ public: return {}; } } + + std::optional build_from_path(std::string_view path) + { + cbindgen_private::ComponentDefinitionOpaque result; + if (cbindgen_private::sixtyfps_interpreter_component_compiler_build_from_path( + &inner, sixtyfps::private_api::string_to_slice(path), &result)) { + + return ComponentDefinition(result); + } else { + return {}; + } + } }; } diff --git a/api/sixtyfps-cpp/tests/test.60 b/api/sixtyfps-cpp/tests/test.60 new file mode 100644 index 000000000..67c4808a6 --- /dev/null +++ b/api/sixtyfps-cpp/tests/test.60 @@ -0,0 +1,10 @@ +/* LICENSE BEGIN + This file is part of the SixtyFPS Project -- https://sixtyfps.io + Copyright (c) 2020 Olivier Goffart + Copyright (c) 2020 Simon Hausmann + + SPDX-License-Identifier: GPL-3.0-only + This file is also available under commercial licensing terms. + Please contact info@sixtyfps.io for more information. +LICENSE END */ +export Test := Rectangle {} \ No newline at end of file diff --git a/api/sixtyfps-cpp/tests/tests.cpp b/api/sixtyfps-cpp/tests/tests.cpp index 744c492c4..0555a4e06 100644 --- a/api/sixtyfps-cpp/tests/tests.cpp +++ b/api/sixtyfps-cpp/tests/tests.cpp @@ -277,4 +277,16 @@ SCENARIO("Component Compiler") auto result = compiler.build_from_source("export Dummy := Rectangle {}", ""); REQUIRE(result.has_value()); } + + SECTION("Compile failure from path") + { + auto result = compiler.build_from_path(SOURCE_DIR "/file-not-there.60"); + REQUIRE_FALSE(result.has_value()); + } + + SECTION("Compile from path") + { + auto result = compiler.build_from_path(SOURCE_DIR "/tests/test.60"); + REQUIRE(result.has_value()); + } } \ No newline at end of file diff --git a/sixtyfps_runtime/interpreter/api.rs b/sixtyfps_runtime/interpreter/api.rs index 739518fb0..2a64fb1b2 100644 --- a/sixtyfps_runtime/interpreter/api.rs +++ b/sixtyfps_runtime/interpreter/api.rs @@ -1352,6 +1352,26 @@ pub(crate) mod ffi { } } + #[no_mangle] + pub unsafe extern "C" fn sixtyfps_interpreter_component_compiler_build_from_path( + compiler: &mut ComponentCompilerOpaque, + path: Slice, + component_definition_ptr: *mut ComponentDefinitionOpaque, + ) -> bool { + use std::str::FromStr; + match spin_on::spin_on( + compiler + .as_component_compiler_mut() + .build_from_path(PathBuf::from_str(std::str::from_utf8(&path).unwrap()).unwrap()), + ) { + Some(definition) => { + std::ptr::write(component_definition_ptr as *mut ComponentDefinition, definition); + true + } + None => false, + } + } + #[repr(C)] // Note: This needs to stay the size of 1 pointer to allow for the null pointer definition // in the C++ wrapper to allow for the null state.