diff --git a/src/builder.ab b/src/builder.ab deleted file mode 100644 index fa713ff..0000000 --- a/src/builder.ab +++ /dev/null @@ -1,59 +0,0 @@ -// Nixie © Karim Vergnes -// Licensed under GNU GPLv2 -// Functions to build Nix and its dependencies from source - -import { set_title } from "./term.ab" -import { check_deps, bail } from "./common.ab" -import { pull_source_file, pull_binary } from "./resources.ab" - -fun build_openssl() -{ - -} - - -fun build_lowdown() -{ - -} - -fun build_nlohmann_json() -{ - -} - -fun build_boost() -{ - -} - -/// Build a dependency which uses Autoconf as its build system. -/// -/// ### Arguments: -/// - `lib_name`: The library to check for with `pkg-config` -/// - `var_name`: The variable to export library locations -/// - `lib_prefix`: Where in the source tree the resulting libraries are found -/// - `inc_prefix`: Where in the source tree the build headers are found -fun build_autoconf_dep(lib_name: Text, var_name: Text, - lib_prefix: Text = "", - inc_prefix: Text = ""): Null -{ - -} - -/// Export libraries found inside the macOS SDK for building Nix -fun darwin_export_sdk() -{ - -} - -/// Build Nix and its dependencies locally, then place it in the expected location -/// in the user's cache directory. -/// -/// This process **requires**, among other things, `pkg-config` to determine -/// which dependencies are already met and avoid building them. -pub fun build_nix() -{ - check_deps(["cc", "c++", "pkg-config", "make", "flex", "bison", "perl"]) - failed { bail("Failed to build Nix from source") } -} diff --git a/src/builders.ab b/src/builders.ab new file mode 100644 index 0000000..82014ee --- /dev/null +++ b/src/builders.ab @@ -0,0 +1,68 @@ +// Nixie © Karim Vergnes +// Licensed under GNU GPLv2 +// Functions to build Nix and its dependencies from source + +import { dir_exists } from "std/fs" +import { env_var_set } from "std/env" + +import { set_title } from "./term.ab" +import { check_deps, bail } from "./common.ab" +import { pull_source_file, pull_binary } from "./resources.ab" +import { get_osname } from "./platform.ab" + +import { build_openssl } from "./builders/openssl.ab" +import { build_lowdown } from "./builders/lowdown.ab" +import { build_nlohmann_json } from "./builders/nlohmann_json.ab" +import { build_boost } from "./builders/boost.ab" +import { build_autoconf_dep } from "./builders/autoconf.ab" +import { build_nix } from "./builders/nix.ab" + +/// Export libraries found inside the macOS SDK for building Nix +fun darwin_export_sdk() +{ + // Calling xcrun should prompt the user to install the macOS SDK. + let sdk_path = trust $xcrun --show-sdk-path$ + + if not dir_exists(sdk_path): + bail("The macOS SDK from Xcode or CommandLineTools is required to build Nix.") + + let sdk_libs = "{sdk_path}/usr/lib" + let sdk_cflags = "-I{sdk_path}/usr/include" + + trust env_var_set("LIBCURL_LIBS", sdk_libs) + trust env_var_set("LIBCURL_CFLAGS", sdk_cflags) + trust env_var_set("LIBARCHIVE_LIBS", sdk_libs) + trust env_var_set("LIBARCHIVE_CFLAGS", sdk_cflags) + trust env_var_set("OPENSSL_LIBS", sdk_libs) + trust env_var_set("OPENSSL_CFLAGS", sdk_cflags) + + trust $export LIBCURL_LIBS LIBCURL_CFLAGS \ + LIBARCHIVE_LIBS LIBARCHIVE_CFLAGS \ + OPENSSL_LIBS OPENSSL_CFLAGS$ +} + +/// Build Nix and its dependencies locally, then place it in the expected location +/// in the user's cache directory. +/// +/// This process **requires**, among other things, `pkg-config` to determine +/// which dependencies are already met and avoid building them. +pub fun try_build_nix() +{ + check_deps(["cc", "c++", "pkg-config", "make", "flex", "bison", "perl"]) + failed { bail("Missing required dependencies to build from source.") } + + if get_osname() == "Darwin": + darwin_export_sdk() + + trust env_var_set("step_total", "8") + + build_openssl()? + build_boost()? + build_nlohmann_json()? + build_lowdown()? + // pkgconf name env var lib prefix include prefix + build_autoconf_dep("libbrotlicommon", "LIBBROTLI", "", "c")? + build_autoconf_dep("libsodium", "SODIUM", "src/libsodium", "src/libsodium")? + build_autoconf_dep("libeditline", "EDITLINE", "src")? + build_nix()? +} diff --git a/src/builders/autoconf.ab b/src/builders/autoconf.ab new file mode 100644 index 0000000..9e402f7 --- /dev/null +++ b/src/builders/autoconf.ab @@ -0,0 +1,22 @@ +// Nixie © Karim Vergnes +// Licensed under GNU GPLv2 +// Build script for Autoconf-based dependencies + +import { pkg_exists, step_title } from "./common.ab" + +/// Build a dependency which uses Autoconf as its build system. +/// +/// ### Arguments: +/// - `lib_name`: The library to check for with `pkg-config` +/// - `var_name`: The variable to export library locations +/// - `lib_prefix`: Where in the source tree the resulting libraries are found +/// - `inc_prefix`: Where in the source tree the build headers are found +pub fun build_autoconf_dep(lib_name: Text, var_name: Text, + lib_prefix: Text = "", + inc_prefix: Text = ""): Null +{ + step_title(lib_name) + + if pkg_exists(lib_name): + return null +} diff --git a/src/builders/boost.ab b/src/builders/boost.ab new file mode 100644 index 0000000..595cc0d --- /dev/null +++ b/src/builders/boost.ab @@ -0,0 +1,37 @@ +// Nixie © Karim Vergnes +// Licensed under GNU GPLv2 +// Builder for the Boost C++ framework + +import { file_exists, dir_exists } from "std/fs" + +import { pkg_exists, step_title } from "./common.ab" + +const modules = ["chrono", "container", "context", "system", "thread"] + +/// Check that the Boost modules we need exist on the system. +/// +/// Boost does not provide a pkg-config package, nor a config program. +/// This means we have to do the information-gathering the old way, by +/// looking through /usr and /usr/local manually. +fun find_boost_libs(libs: [Text]): Bool +{ + for lib in libs { + let libname = "libboost_{lib}*" + if not ( file_exists("/usr/lib/{libname}") + or file_exists("/usr/local/lib/{libname}")): + return false + if not ( dir_exists("/usr/include/boost/{lib}") + or dir_exists("/usr/local/include/boost/{lib}")): + return false + } + + return true +} + +pub fun build_boost() +{ + step_title("boost") + + if find_boost_libs(["atomic"] + modules): + return 0 +} diff --git a/src/builders/common.ab b/src/builders/common.ab new file mode 100644 index 0000000..f3a7806 --- /dev/null +++ b/src/builders/common.ab @@ -0,0 +1,28 @@ +// Nixie © Karim Vergnes +// Licensed under GNU GPLv2 +// Common functions for source-based builders + +import { env_var_get } from "std/env" + +import { set_title } from "../term.ab" + +let step_current = 1 + +/// Invoke `pkg-config` to assert that a given dependency exists on the system. +pub fun pkg_exists(package: Text): Bool +{ + $pkg-config {package}$ failed { + return false + } + + return true +} + +pub fun step_title(name: Text): Null +{ + let step_total = trust env_var_get("step_total") + + set_title("Building Nix: {name} ({step_current}/{step_total})") + + step_current += 1 +} diff --git a/src/builders/lowdown.ab b/src/builders/lowdown.ab new file mode 100644 index 0000000..dd4d162 --- /dev/null +++ b/src/builders/lowdown.ab @@ -0,0 +1,18 @@ +// Nixie © Karim Vergnes +// Licensed under GNU GPLv2 +// Builder for the lowdown Markdown library + +import { pkg_exists, step_title } from "./common.ab" + +fun macos_build_post() +{ + $cc -shared -o liblowdown.1.dylib *.o$? +} + +pub fun build_lowdown() +{ + step_title("lowdown") + + if pkg_exists("lowdown"): + return 0 +} diff --git a/src/builders/nix.ab b/src/builders/nix.ab new file mode 100644 index 0000000..748d564 --- /dev/null +++ b/src/builders/nix.ab @@ -0,0 +1,12 @@ +// Nixie © Karim Vergnes +// Licensed under GNU GPLv2 +// Builder for the Nix package manager itself + +import { file_exists, dir_exists } from "std/fs" + +import { step_title } from "./common.ab" + +pub fun build_nix() +{ + step_title("nix") +} diff --git a/src/builders/nlohmann_json.ab b/src/builders/nlohmann_json.ab new file mode 100644 index 0000000..13bc906 --- /dev/null +++ b/src/builders/nlohmann_json.ab @@ -0,0 +1,13 @@ +// Nixie © Karim Vergnes +// Licensed under GNU GPLv2 +// Builder for NLohmann's JSON library + +import { pkg_exists, step_title } from "./common.ab" + +pub fun build_nlohmann_json() +{ + step_title("nlohmann_json") + + if pkg_exists("nlohmann_json"): + return 0 +} diff --git a/src/builders/openssl.ab b/src/builders/openssl.ab new file mode 100644 index 0000000..334f82d --- /dev/null +++ b/src/builders/openssl.ab @@ -0,0 +1,22 @@ +// Nixie © Karim Vergnes +// Licensed under GNU GPLv2 +// Builder for OpenSSL + +import { pkg_exists, step_title } from "./common.ab" + +/// Scans through and builds generated headers required for building OpenSSL. +/// +/// For some reason the OpenSSL Makefile does not specify dependencies to those +/// targets, meaning we cannot simply build `libcrypto.so`. +fun make_headers() +{ + +} + +pub fun build_openssl() +{ + step_title("libcrypto") + + if pkg_exists("libcrypto"): + return 0 +} diff --git a/src/cli.ab b/src/cli.ab index 509006a..080fda3 100644 --- a/src/cli.ab +++ b/src/cli.ab @@ -69,6 +69,15 @@ fun opt_ignore_system() trust env_var_set("nosystem", "1") } +//TODO: debug function, remove! +fun no_precompiled() +{ + echo_warning("Ignoring precompiled binaries for testing purposes.") + echo_warning("This implies --nixie-ignore-system.") + trust env_var_set("nobins", "1") + trust env_var_set("nosystem", "1") +} + fun notfound(cmd) { let self = trust env_var_get("0") @@ -84,6 +93,7 @@ fun eval_cmd(cmd) cmd == "extract": cmd_extract() cmd == "cleanup": cmd_cleanup() cmd == "ignore-system": opt_ignore_system() + cmd == "no-precompiled":no_precompiled() else: notfound(cmd) } } diff --git a/src/nix.ab b/src/nix.ab index e966be7..0af3db9 100644 --- a/src/nix.ab +++ b/src/nix.ab @@ -9,7 +9,7 @@ import { enter_alt_buffer, set_title, teardown } from "./term.ab" import { bail } from "./common.ab" import { get_osname, get_system, get_cache_root, get_nix_root } from "./platform.ab" import { pull_binary } from "./resources.ab" -import { build_nix } from "./builder.ab" +import { try_build_nix } from "./builders.ab" /// Determine whether Nix is installed system-wide. Nixie can launch the /// system-wide Nix when it is available, using the script's bundled options. @@ -67,9 +67,16 @@ fun get_nix() return 0 } + //TODO: Debug! Remove before release! + if env_var_test("nobins") { + trust try_build_nix() + teardown() + fail status + } + // Try to extract or download Nix pull_binary("nix.{system}", nix_path) failed { - trust build_nix() + trust try_build_nix() teardown() fail status } diff --git a/src/term.ab b/src/term.ab index ba17898..f38b2f0 100644 --- a/src/term.ab +++ b/src/term.ab @@ -2,21 +2,55 @@ // Licensed under GNU GPLv2 // Utilities to manipulate Xterm features -let tsl = trust $tput tsl$ //TODO: improve logic to match xterm+sl -let fsl = trust $tput fsl$ //TODO: as above +import { env_var_get } from "std/env" +import { starts_with } from "std/text" + +let tsl = trust $tput tsl$ +let fsl = trust $tput fsl$ let smcup = trust $tput smcup$ let rmcup = trust $tput rmcup$ +let TERM = trust env_var_get("TERM") + +fun can_set_title(): Bool +{ + let has_statusline = true + + $tput hs$ failed { + // For some reason, default xterm won't communicate statusline. + // We need to set TERM=xterm+sl to get the info. + if starts_with(TERM, "xterm") { + trust $TERM=xterm+sl tput hs$ + if status == 0 { + tsl = trust $TERM=xterm+sl tput tsl$ + fsl = trust $TERM=xterm+sl tput fsl$ + } else { + has_statusline = false + } + } else { + has_statusline = false + } + } + + return has_statusline +} + +/// Set the title for the current window, if possible. +/// +/// Does nothing otherwise. pub fun set_title(title: Text = ""): Null { - echo "{tsl}{title} {fsl}" + if can_set_title(): + echo tsl + title + fsl } +/// Create and enter an alt-buffer in the terminal. pub fun enter_alt_buffer(): Null { echo smcup } +/// Close the alt-buffer in the terminal. pub fun exit_alt_buffer(): Null { echo rmcup