Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extension installation rework #4066

Merged
merged 19 commits into from
Aug 23, 2024
67 changes: 16 additions & 51 deletions .github/workflows/build-extensions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,13 @@ jobs:
run: make extension-release NUM_THREADS=$(nproc)

- name: Collect built artifacts
run: |
mkdir -p extension-artifacts
find extension -type f -name "*.kuzu_extension" -exec cp {} extension-artifacts \;
run: /opt/python/cp310-cp310/bin/python scripts/collect-extensions.py

- name: Upload built artifacts
uses: actions/upload-artifact@v4
with:
name: kuzu-extensions_linux-x86_64
path: extension-artifacts/*.kuzu_extension
path: extension-artifacts

build-linux-extensions-aarch64:
runs-on: kuzu-self-hosted-linux-building-aarch64
Expand All @@ -32,15 +30,13 @@ jobs:
run: make extension-release NUM_THREADS=$(nproc)

- name: Collect built artifacts
run: |
mkdir -p extension-artifacts
find extension -type f -name "*.kuzu_extension" -exec cp {} extension-artifacts \;
run: /opt/python/cp310-cp310/bin/python scripts/collect-extensions.py

- name: Upload built artifacts
uses: actions/upload-artifact@v4
with:
name: kuzu-extensions_linux-aarch64
path: extension-artifacts/*.kuzu_extension
path: extension-artifacts

build-linux-extensions-x86:
runs-on: ubuntu-latest
Expand All @@ -52,7 +48,7 @@ jobs:
run: |
docker run -d --name kuzu-x86 \
-v $PWD:/kuzu -w /kuzu \
-e NUM_THREADS=2 -e CC=gcc -e CXX=g++ \
-e NUM_THREADS=$(nproc) -e CC=gcc -e CXX=g++ \
i386/debian:stable tail -f /dev/null

- name: Install dependencies
Expand All @@ -66,16 +62,15 @@ jobs:

- name: Collect built artifacts
run: |
mkdir -p extension-artifacts
find extension -type f -name "*.kuzu_extension" -exec cp {} extension-artifacts \;
python3 scripts/collect-extensions.py
sudo chown -R $USER:$USER extension-artifacts
sudo chmod -R 755 extension-artifacts

- name: Upload built artifacts
uses: actions/upload-artifact@v4
with:
name: kuzu-extensions_linux-x86
path: extension-artifacts/*.kuzu_extension
path: extension-artifacts

- name: Stop Docker container
run: docker stop kuzu-x86
Expand All @@ -92,15 +87,13 @@ jobs:
CMAKE_OSX_ARCHITECTURES: "arm64"

- name: Collect built artifacts
run: |
mkdir -p extension-artifacts
find extension -type f -name "*.kuzu_extension" -exec cp {} extension-artifacts \;
run: python3 scripts/collect-extensions.py

- name: Upload built artifacts
uses: actions/upload-artifact@v4
with:
name: kuzu-extensions_osx-arm64
path: extension-artifacts/*.kuzu_extension
path: extension-artifacts

build-mac-extensions-x86_64:
runs-on: self-hosted-mac-x64
Expand All @@ -114,15 +107,13 @@ jobs:
CMAKE_OSX_ARCHITECTURES: "x86_64"

- name: Collect built artifacts
run: |
mkdir -p extension-artifacts
find extension -type f -name "*.kuzu_extension" -exec cp {} extension-artifacts \;
run: python3 scripts/collect-extensions.py

- name: Upload built artifacts
uses: actions/upload-artifact@v4
with:
name: kuzu-extensions_osx-x86_64
path: extension-artifacts/*.kuzu_extension
path: extension-artifacts

build-windows-extensions-x86_64:
runs-on: self-hosted-windows
Expand All @@ -138,15 +129,13 @@ jobs:
make extension-release

- name: Collect built artifacts
run: |
mkdir -p extension-artifacts
Get-ChildItem -Path .\extension -Recurse -Filter "*.kuzu_extension" | ForEach-Object {Copy-Item $_.FullName -Destination extension-artifacts -Force}
run: python scripts/collect-extensions.py

- name: Upload built artifacts
uses: actions/upload-artifact@v4
with:
name: kuzu-extensions_win-x86_64
path: extension-artifacts/*.kuzu_extension
path: extension-artifacts

update-extensions-repo:
runs-on: ubuntu-latest
Expand All @@ -172,23 +161,9 @@ jobs:
repository: kuzudb/extension
token: ${{ secrets.DOC_PUSH_TOKEN }}

- name: Ensure extension directories
run: |
mkdir -p releases/$RELEASE_VERSION/linux_amd64
mkdir -p releases/$RELEASE_VERSION/linux_arm64
mkdir -p releases/$RELEASE_VERSION/linux_x86
mkdir -p releases/$RELEASE_VERSION/osx_amd64
mkdir -p releases/$RELEASE_VERSION/osx_arm64
mkdir -p releases/$RELEASE_VERSION/win_amd64

- name: Clear old artifacts
run: |
rm -rf releases/$RELEASE_VERSION/linux_amd64/*
rm -rf releases/$RELEASE_VERSION/linux_arm64/*
rm -rf releases/$RELEASE_VERSION/linux_x86/*
rm -rf releases/$RELEASE_VERSION/osx_amd64/*
rm -rf releases/$RELEASE_VERSION/osx_arm64/*
rm -rf releases/$RELEASE_VERSION/win_amd64/*
rm -rf releases/$RELEASE_VERSION/

- name: Create temporary directory for artifacts
run: |
Expand Down Expand Up @@ -238,24 +213,14 @@ jobs:

- name: Copy built artifacts
run: |
cp extension-artifacts/linux_amd64/*.kuzu_extension releases/$RELEASE_VERSION/linux_amd64
cp extension-artifacts/linux_arm64/*.kuzu_extension releases/$RELEASE_VERSION/linux_arm64
cp extension-artifacts/linux_x86/*.kuzu_extension releases/$RELEASE_VERSION/linux_x86
cp extension-artifacts/osx_amd64/*.kuzu_extension releases/$RELEASE_VERSION/osx_amd64
cp extension-artifacts/osx_arm64/*.kuzu_extension releases/$RELEASE_VERSION/osx_arm64
cp extension-artifacts/win_amd64/*.kuzu_extension releases/$RELEASE_VERSION/win_amd64
rsync -av extension-artifacts/ releases/$RELEASE_VERSION/

- name: Remove temporary directory
run: rm -rf extension-artifacts

- name: Set artifact permissions
run: |
chmod 755 releases/$RELEASE_VERSION/linux_amd64/*
chmod 755 releases/$RELEASE_VERSION/linux_arm64/*
chmod 755 releases/$RELEASE_VERSION/linux_x86/*
chmod 755 releases/$RELEASE_VERSION/osx_amd64/*
chmod 755 releases/$RELEASE_VERSION/osx_arm64/*
chmod 755 releases/$RELEASE_VERSION/win_amd64/*
chmod -R 755 releases/$RELEASE_VERSION

- name: List downloaded artifacts
run: ls -R releases/$RELEASE_VERSION
Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ add_subdirectory(third_party)
if(${BUILD_KUZU})
add_definitions(-DKUZU_ROOT_DIRECTORY="${PROJECT_SOURCE_DIR}")
add_definitions(-DKUZU_CMAKE_VERSION="${CMAKE_PROJECT_VERSION}")
add_definitions(-DKUZU_EXTENSION_VERSION="0.5.1.11")
add_definitions(-DKUZU_EXTENSION_VERSION="0.5.2.0")

include_directories(src/include)

Expand Down
1 change: 0 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,6 @@ extension-test-build:
$(call run-cmake-release, \
-DBUILD_EXTENSIONS="httpfs;duckdb;json;postgres;sqlite" \
-DBUILD_EXTENSION_TESTS=TRUE \
-DENABLE_ADDRESS_SANITIZER=TRUE \
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why remove asan from extension test?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

duckdb doesn't compile with asan, if we compile with asan linking with duckdb will cause a linking error in windows.

)

extension-json-test-build:
Expand Down
55 changes: 45 additions & 10 deletions extension/duckdb/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
# Address sanitizer may change the ABI, so we use dynamic linking
# if it's enabled.
if(${ENABLE_ADDRESS_SANITIZER})
set(DuckDB_USE_STATIC_LIBS OFF)
else()
set(DuckDB_USE_STATIC_LIBS ON)
endif()
if (WIN32)
set(DuckDB_USE_STATIC_LIBS ON)
else ()
set(DuckDB_USE_STATIC_LIBS OFF)
endif ()

find_package(DuckDB REQUIRED)
if(NOT WIN32)
find_library(DuckDB_STATIC REQUIRED NAMES libduckdb_static.a)
endif()

include_directories(
${PROJECT_SOURCE_DIR}/src/include
Expand Down Expand Up @@ -44,6 +40,43 @@ set_target_properties(duckdb_extension PROPERTIES
SUFFIX ".kuzu_extension"
)

if (NOT WIN32)
add_library(duckdb_extension_installer
SHARED
src/duckdb_installer.cpp
src/duckdb_install_func.cpp)

add_library(duckdb_extension_loader
SHARED
src/duckdb_loader.cpp)

set_target_properties(duckdb_extension_installer
PROPERTIES
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/build"
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/build"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/build"
)

set_target_properties(duckdb_extension_loader
PROPERTIES
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/build"
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/build"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/build"
)

set_target_properties(duckdb_extension_installer PROPERTIES
OUTPUT_NAME duckdb_installer
PREFIX "lib"
SUFFIX ".kuzu_extension"
)

set_target_properties(duckdb_extension_loader PROPERTIES
OUTPUT_NAME duckdb_loader
PREFIX "lib"
SUFFIX ".kuzu_extension"
)
endif ()

if (WIN32)
# On windows, there is no dynamic lookup available, so it's not
# possible to generically look for symbols on library load. There are
Expand All @@ -66,4 +99,6 @@ endif()

if (APPLE)
set_target_properties(duckdb_extension PROPERTIES LINK_FLAGS "-undefined dynamic_lookup")
set_target_properties(duckdb_extension_installer PROPERTIES LINK_FLAGS "-undefined dynamic_lookup")
set_target_properties(duckdb_extension_loader PROPERTIES LINK_FLAGS "-undefined dynamic_lookup")
endif ()
15 changes: 15 additions & 0 deletions extension/duckdb/src/duckdb_install_func.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#include "duckdb_installer.h"

extern "C" {
// Because we link against the static library on windows, we implicitly inherit KUZU_STATIC_DEFINE,
// which cancels out any exporting, so we can't use KUZU_API.
#if defined(_WIN32)
#define INIT_EXPORT __declspec(dllexport)
#else
#define INIT_EXPORT __attribute__((visibility("default")))
#endif
INIT_EXPORT void install(kuzu::main::ClientContext* context) {
kuzu::duckdb_extension::DuckDBInstaller installer{"duckdb"};
installer.install(context);
}
}
29 changes: 29 additions & 0 deletions extension/duckdb/src/duckdb_installer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#include "duckdb_installer.h"

#include "common/file_system/virtual_file_system.h"
#include "duckdb_extension.h"
#include "main/client_context.h"

namespace kuzu {
namespace duckdb_extension {

void DuckDBInstaller::install(main::ClientContext* context) {
auto loaderFileRepoInfo = extension::ExtensionUtils::getExtensionLoaderRepoInfo(extensionName);
auto localLoaderFilePath =
extension::ExtensionUtils::getLocalPathForExtensionLoader(context, extensionName);
tryDownloadExtensionFile(context, loaderFileRepoInfo, localLoaderFilePath);

for (auto& dependencyLib : DuckDBExtension::DEPENDENCY_LIB_FILES) {
auto dependencyLibWithSuffix = extension::ExtensionUtils::appendLibSuffix(dependencyLib);
auto localDependencyLibPath =
extension::ExtensionUtils::getLocalPathForSharedLib(context, dependencyLibWithSuffix);
if (!context->getVFSUnsafe()->fileOrPathExists(localDependencyLibPath)) {
auto dependencyLibRepoInfo =
extension::ExtensionUtils::getSharedLibRepoInfo(dependencyLibWithSuffix);
tryDownloadExtensionFile(context, dependencyLibRepoInfo, localDependencyLibPath);
}
}
}

} // namespace duckdb_extension
} // namespace kuzu
32 changes: 32 additions & 0 deletions extension/duckdb/src/duckdb_loader.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#include "duckdb_loader.h"

#include "duckdb_extension.h"

namespace kuzu {
namespace duckdb_extension {

void DuckDBLoader::loadDependency(main::ClientContext* context) {
for (auto& dependencyLib : DuckDBExtension::DEPENDENCY_LIB_FILES) {
auto dependencyLibWithSuffix = extension::ExtensionUtils::appendLibSuffix(dependencyLib);
auto dependencyLibPath =
extension::ExtensionUtils::getLocalPathForSharedLib(context, dependencyLibWithSuffix);
auto dependencyLoader = extension::ExtensionLibLoader(extensionName, dependencyLibPath);
}
}

} // namespace duckdb_extension
} // namespace kuzu

extern "C" {
// Because we link against the static library on windows, we implicitly inherit KUZU_STATIC_DEFINE,
// which cancels out any exporting, so we can't use KUZU_API.
#if defined(_WIN32)
#define INIT_EXPORT __declspec(dllexport)
#else
#define INIT_EXPORT __attribute__((visibility("default")))
#endif
INIT_EXPORT void load(kuzu::main::ClientContext* context) {
kuzu::duckdb_extension::DuckDBLoader loader{"duckdb"};
loader.loadDependency(context);
}
}
1 change: 1 addition & 0 deletions extension/duckdb/src/include/duckdb_extension.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ namespace duckdb_extension {
class DuckDBExtension final : public extension::Extension {
public:
static constexpr char EXTENSION_NAME[] = "DUCKDB";
static constexpr const char* DEPENDENCY_LIB_FILES[] = {"libduckdb"};

public:
static void load(main::ClientContext* context);
Expand Down
16 changes: 16 additions & 0 deletions extension/duckdb/src/include/duckdb_installer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#pragma once
#include "extension/extension_installer.h"

namespace kuzu {
namespace duckdb_extension {

class DuckDBInstaller : public extension::ExtensionInstaller {
public:
explicit DuckDBInstaller(const std::string extensionName)
: ExtensionInstaller{std::move(extensionName)} {}

void install(main::ClientContext* context) override;
};

} // namespace duckdb_extension
} // namespace kuzu
16 changes: 16 additions & 0 deletions extension/duckdb/src/include/duckdb_loader.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#pragma once
#include "extension/extension_loader.h"

namespace kuzu {
namespace duckdb_extension {

class DuckDBLoader final : public extension::ExtensionLoader {
public:
explicit DuckDBLoader(std::string extensionName)
: extension::ExtensionLoader{std::move(extensionName)} {}

void loadDependency(main::ClientContext* context) override;
};

} // namespace duckdb_extension
} // namespace kuzu
Loading
Loading