Implemented multi-binary app packaging (#648)
This commit is contained in:
committed by
GitHub
parent
2496dea5c2
commit
8556103eb1
@@ -58,19 +58,21 @@ bool is_executable_file(const std::string& resolved_path) {
|
||||
#endif
|
||||
}
|
||||
|
||||
// location.location can be either an app's install directory or the .so file directly; the
|
||||
// former resolves to the per-architecture binary at {dir}/elf/posix-{TACTILITY_POSIX_ARCH}.so,
|
||||
// mirroring app_esp32_loader_service.cpp's resolve_elf_path().
|
||||
// location.location can be either an app's install directory or the .so file directly, mirroring
|
||||
// app_esp32_loader_service.cpp's resolve_elf_path(). A "packaged" app's install directory always
|
||||
// holds its single binary at the fixed path {dir}/bin/posix-{TACTILITY_POSIX_ARCH}/app.so - a
|
||||
// "terminal" app has no such file (its several binaries keep their own names), so this correctly
|
||||
// leaves it unresolvable - terminal apps aren't run through AppLoaderApi (see app/install.h).
|
||||
error_t resolve_app_path(const std::string& path, std::string& resolvedPath) {
|
||||
if (path.ends_with(".so")) {
|
||||
resolvedPath = path;
|
||||
return ERROR_NONE;
|
||||
}
|
||||
std::string shared_object_path = path + "/elf/posix-" TACTILITY_POSIX_ARCH ".so";
|
||||
if (!is_regular_file(shared_object_path)) {
|
||||
std::string candidate = path + "/bin/posix-" TACTILITY_POSIX_ARCH "/app.so";
|
||||
if (!is_regular_file(candidate)) {
|
||||
return ERROR_NOT_FOUND;
|
||||
}
|
||||
resolvedPath = shared_object_path;
|
||||
resolvedPath = candidate;
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
@@ -94,9 +96,6 @@ error_t api_load(AppLocation location, AppRuntime* out_runtime) {
|
||||
|
||||
LOG_I(TAG, "Loading %s", app_path.c_str());
|
||||
|
||||
// RTLD_NOW: a missing symbol fails here, not mid-run(). RTLD_LOCAL: this app's own exported
|
||||
// symbols (if any beyond its entry point) don't leak into the process's global scope and
|
||||
// clash with a different app's.
|
||||
void* handle = dlopen(app_path.c_str(), RTLD_NOW | RTLD_LOCAL);
|
||||
if (handle == nullptr) {
|
||||
LOG_E(TAG, "dlopen(%s) failed: %s", app_path.c_str(), dlerror());
|
||||
@@ -117,8 +116,8 @@ error_t api_load(AppLocation location, AppRuntime* out_runtime) {
|
||||
int32_t api_run(AppRuntime runtime_ptr, uint32_t /*app_instance_id*/, int argc, char* argv[]) {
|
||||
auto* runtime = static_cast<PosixAppRuntime*>(runtime_ptr);
|
||||
|
||||
dlerror(); // clear any pending error, per dlsym(3)'s own recommended idiom for telling a NULL
|
||||
// symbol address apart from a real lookup failure
|
||||
// Clear any pending error, per dlsym(3)'s own recommended idiom for telling a NULL symbol address apart from a real lookup failure
|
||||
dlerror();
|
||||
void* symbol = dlsym(runtime->handle, "main");
|
||||
const char* lookup_error = dlerror();
|
||||
if (symbol == nullptr || lookup_error != nullptr) {
|
||||
|
||||
@@ -15,14 +15,27 @@ set_target_properties(app_posix_module_test_fixture PROPERTIES POSITION_INDEPEND
|
||||
set(NON_ELF_FIXTURE_PATH "${CMAKE_CURRENT_BINARY_DIR}/not-elf.so")
|
||||
file(WRITE "${NON_ELF_FIXTURE_PATH}" "not an elf file")
|
||||
|
||||
# An install-directory-shaped fixture: {dir}/bin/posix-{arch}/app.so, matching where
|
||||
# app_posix_loader_service.cpp's resolve_app_path() looks for a "packaged" app's single binary.
|
||||
set(INSTALL_DIR_FIXTURE_PATH "${CMAKE_CURRENT_BINARY_DIR}/install-dir-fixture")
|
||||
set(INSTALL_DIR_FIXTURE_BIN_DIR "${INSTALL_DIR_FIXTURE_PATH}/bin/posix-${CMAKE_SYSTEM_PROCESSOR}")
|
||||
add_custom_command(
|
||||
OUTPUT "${INSTALL_DIR_FIXTURE_BIN_DIR}/app.so"
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory "${INSTALL_DIR_FIXTURE_BIN_DIR}"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy "$<TARGET_FILE:app_posix_module_test_fixture>" "${INSTALL_DIR_FIXTURE_BIN_DIR}/app.so"
|
||||
DEPENDS app_posix_module_test_fixture
|
||||
)
|
||||
add_custom_target(install_dir_fixture DEPENDS "${INSTALL_DIR_FIXTURE_BIN_DIR}/app.so")
|
||||
|
||||
file(GLOB_RECURSE TEST_SOURCES CONFIGURE_DEPENDS ${PROJECT_SOURCE_DIR}/source/*.cpp)
|
||||
add_executable(AppPosixModuleTests EXCLUDE_FROM_ALL ${TEST_SOURCES})
|
||||
add_dependencies(AppPosixModuleTests app_posix_module_test_fixture)
|
||||
add_dependencies(AppPosixModuleTests app_posix_module_test_fixture install_dir_fixture)
|
||||
|
||||
target_include_directories(AppPosixModuleTests PRIVATE ${DOCTESTINC})
|
||||
target_compile_definitions(AppPosixModuleTests PRIVATE
|
||||
FIXTURE_APP_PATH="$<TARGET_FILE:app_posix_module_test_fixture>"
|
||||
FIXTURE_NON_ELF_PATH="${NON_ELF_FIXTURE_PATH}"
|
||||
FIXTURE_INSTALL_DIR_PATH="${INSTALL_DIR_FIXTURE_PATH}"
|
||||
)
|
||||
|
||||
add_test(NAME AppPosixModuleTests COMMAND AppPosixModuleTests)
|
||||
|
||||
@@ -148,6 +148,12 @@ TEST_CASE("app_is_executable() rejects a nonexistent path") {
|
||||
TEST_CASE("app_is_executable() rejects an install-directory-shaped path missing its per-arch .so") {
|
||||
ensure_path_loader_registered();
|
||||
|
||||
// FIXTURE_DIR itself has no elf/posix-<arch>.so under it, so resolution fails.
|
||||
// FIXTURE_DIR itself has no bin/posix-<arch>/app.so under it, so resolution fails.
|
||||
CHECK_FALSE(is_executable_path(FIXTURE_DIR.c_str()));
|
||||
}
|
||||
|
||||
TEST_CASE("app_is_executable() accepts an install-directory-shaped path with bin/<arch>/app.so") {
|
||||
ensure_path_loader_registered();
|
||||
|
||||
CHECK(is_executable_path(FIXTURE_INSTALL_DIR_PATH));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user