blob: a259dc22961058b0ba88b12f8093e2adbf03ea89 [file] [log] [blame]
#!/usr/bin/env dub
/+ dub.sdl:
name "build"
dependency "std" version="*"
+/
/**
* OpenDAL D Bindings Build Script
*
* This script builds the OpenDAL C library with specified features
* and copies the necessary files for D bindings.
*
* This script is automatically executed during:
* dub build
* dub test
* dub run
*
* For manual execution with custom options:
* OPENDAL_TEST=memory dmd -run build.d
* OPENDAL_TEST=fs OPENDAL_VERBOSE=1 dmd -run build.d release
*/
module build;
import std.stdio : writeln, stderr;
import std.path : buildPath;
import std.process : spawnShell, wait, environment;
import std.exception : enforce;
import std.file : copy, mkdir, exists;
import std.conv : to;
import std.string : startsWith, split, strip, toLower;
import std.array : join;
version (Windows)
enum staticlib = "opendal_c.lib";
else
enum staticlib = "libopendal_c.a";
struct BuildConfig
{
bool isRelease;
string[] services;
bool verbose;
bool help;
}
void printHelp()
{
writeln("OpenDAL D Bindings Build Script");
writeln();
writeln("This script is automatically executed during:");
writeln(" dub build - Build the D bindings");
writeln(" dub test - Run unit tests");
writeln(" dub run - Build and run examples");
writeln();
writeln("Environment Variables (for use with dub commands):");
writeln(" OPENDAL_TEST The service to test (e.g., fs, s3, memory, etc.)");
writeln(" OPENDAL_{SERVICE}_* Service-specific configuration (e.g., OPENDAL_FS_ROOT)");
writeln(" OPENDAL_VERBOSE Set to '1' or 'true' for verbose output");
writeln();
writeln("Examples with environment variables:");
writeln(" OPENDAL_TEST=memory dub build");
writeln(" OPENDAL_TEST=fs OPENDAL_FS_ROOT=/tmp/test dub test");
writeln(" OPENDAL_TEST=memory OPENDAL_VERBOSE=1 dub build -b release");
writeln();
writeln("For manual execution with command line options:");
writeln(" dmd -run build.d [options]");
writeln();
writeln("Command line options:");
writeln(" release Build in release mode (default: debug)");
writeln(" --verbose Enable verbose output");
writeln(" --help Show this help message");
writeln();
writeln("Manual execution examples:");
writeln(" OPENDAL_TEST=memory dmd -run build.d");
writeln(" OPENDAL_TEST=fs OPENDAL_FS_ROOT=/tmp/test dmd -run build.d release");
writeln(" OPENDAL_TEST=fs OPENDAL_FS_ROOT=/tmp OPENDAL_VERBOSE=1 dmd -run build.d release");
}
BuildConfig parseArgs(string[] args)
{
BuildConfig config;
config.services = []; // No default services - user must specify
// Check environment variables first
auto envTest = environment.get("OPENDAL_TEST", "");
if (envTest.length > 0)
{
config.services = [envTest];
}
auto envVerbose = environment.get("OPENDAL_VERBOSE", "");
if (envVerbose == "1" || envVerbose.toLower() == "true")
{
config.verbose = true;
}
foreach (arg; args[1..$])
{
if (arg == "release")
{
config.isRelease = true;
}
else if (arg == "--verbose")
{
config.verbose = true;
}
else if (arg == "--help" || arg == "-h")
{
config.help = true;
}
else
{
stderr.writeln("Unknown argument: ", arg);
stderr.writeln("Use --help for usage information");
}
}
return config;
}
void buildCargoLibrary(BuildConfig config)
{
// Check if services are specified
if (config.services.length == 0)
{
stderr.writeln("Warning: No OpenDAL service specified for testing!");
stderr.writeln("Use OPENDAL_TEST environment variable to specify the service to test.");
stderr.writeln("Example: OPENDAL_TEST=memory dub build");
stderr.writeln("Available services: memory, fs, s3, etc. (see OpenDAL documentation)");
stderr.writeln();
stderr.writeln("Building with only core functionality (no storage backends)...");
}
// Build features list
string[] features = ["opendal/blocking"];
foreach (service; config.services)
{
features ~= "opendal/services-" ~ service.strip();
}
// Construct cargo command
auto cargoCmd = "cargo build --manifest-path " ~ buildPath("..", "c", "Cargo.toml");
if (config.isRelease)
cargoCmd ~= " --release";
cargoCmd ~= " --features \"" ~ features.join(",") ~ "\"";
if (config.verbose)
cargoCmd ~= " --verbose";
writeln("Building OpenDAL C library...");
writeln("Features: ", features.join(", "));
if (config.verbose)
writeln("Command: ", cargoCmd);
auto status = wait(spawnShell(cargoCmd));
enforce(status == 0, "Cargo build failed with status: " ~ status.to!string);
writeln("✓ Cargo build completed successfully");
}
void copyArtifacts(BuildConfig config)
{
string buildType = config.isRelease ? "release" : "debug";
writeln("Copying build artifacts...");
// Copy header file
auto headerSrc = buildPath("..", "c", "include", "opendal.h");
auto headerDst = buildPath("source", "opendal", "opendal.h");
if (config.verbose)
writeln("Copying header: ", headerSrc, " -> ", headerDst);
copy(headerSrc, headerDst);
// Ensure lib directory exists
if (!exists("lib"))
{
if (config.verbose)
writeln("Creating lib directory");
mkdir("lib");
}
// Copy static library
auto libSrc = buildPath("..", "c", "target", buildType, staticlib);
auto libDst = buildPath("lib", staticlib);
if (config.verbose)
writeln("Copying library: ", libSrc, " -> ", libDst);
copy(libSrc, libDst);
writeln("✓ Build artifacts copied successfully");
}
void main(string[] args)
{
try
{
auto config = parseArgs(args);
if (config.help)
{
printHelp();
return;
}
writeln("OpenDAL D Bindings Build");
writeln("========================");
writeln("Build mode: ", config.isRelease ? "release" : "debug");
writeln("Services: ", config.services.join(", "));
writeln();
buildCargoLibrary(config);
copyArtifacts(config);
writeln();
writeln("✓ Build completed successfully!");
writeln("Ready for: dub build, dub test, or dub run");
}
catch (Exception e)
{
stderr.writeln("❌ Build failed: ", e.msg);
import core.stdc.stdlib : exit;
exit(1);
}
}