diff --git a/plrust/.cargo/config b/.cargo/config similarity index 100% rename from plrust/.cargo/config rename to .cargo/config diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a2a8f102..2fefc4b0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -58,7 +58,7 @@ jobs: run: | cd $WORK_DIR shopt -s globstar - checksum=$(cat **/Cargo.lock **/rust-toolchain.toml .github/workflows/ci.yml | sha256sum | awk '{print $1}') + checksum=$(cat **/Cargo.lock **/rust-toolchain.toml .github/workflows/ci.yml .cargo/config | sha256sum | awk '{print $1}') echo "CACHE_KEY_CHECKSUM=$checksum" >> $GITHUB_ENV - name: Set up (Linux) prerequisites and environment @@ -267,46 +267,13 @@ jobs: cargo --version echo "" - - name: Set up (Mac) prerequisites and environment - if: matrix.os == 'macos-11' - run: | - echo "" - - # https://stackoverflow.com/questions/57968497/how-do-i-set-an-env-var-with-a-bash-expression-in-github-actions/57969570#57969570 - echo "----- Getting pre-installed Postgres major version -----" - PG_VER=$(pg_config --version | awk '{split($2,a,"."); print a[1]}') - echo "PG_VER=$PG_VER" >> $GITHUB_ENV - cat $GITHUB_ENV - - echo "----- Installing yq so .toml files can be parsed and queried -----" - pip3 install yq - echo "" - - echo "----- Setting up RUSTFLAGS found in .cargo/config -----" - echo "RUSTFLAGS=$RUSTFLAGS $(tomlq --raw-output '.build.rustflags | join(" ")' .cargo/config)" >> $GITHUB_ENV - cat $GITHUB_ENV - echo "" - - echo "----- Set up Postgres permissions -----" - sudo chmod a+rwx `$(which pg_config) --pkglibdir` `$(which pg_config) --sharedir`/extension - ls -lath `$(which pg_config) --pkglibdir` `$(which pg_config) --sharedir`/extension - echo "" - - echo "----- Output Cargo version -----" - cargo --version - echo "" - - echo "----- Outputting env -----" - env - echo "" - - name: Cache cargo registry uses: actions/cache@v3 continue-on-error: false with: path: | /home/runner/.cargo - key: v0-plrust-x86_64-cargo-${{ runner.os }}-${{ hashFiles('**/Cargo.lock', '**/rust-toolchain.toml', 'plrustc/.cargo/config.toml', '.github/workflows/ci.yml') }} + key: v0-plrust-x86_64-cargo-${{ runner.os }}-${{ hashFiles('**/Cargo.lock', '**/rust-toolchain.toml', 'plrustc/.cargo/config.toml', '.github/workflows/ci.yml', '.cargo/config') }} - name: Cache sccache directory uses: actions/cache@v3 @@ -314,7 +281,7 @@ jobs: with: path: | /home/runner/.cache/sccache - key: v0-plrust-x86_64-sccache-${{ matrix.target }}-${{ runner.os }}-${{ hashFiles('**/Cargo.lock', '**/rust-toolchain.toml', 'plrustc/.cargo/config.toml', '.github/workflows/ci.yml') }} + key: v0-plrust-x86_64-sccache-${{ matrix.target }}-${{ runner.os }}-${{ hashFiles('**/Cargo.lock', '**/rust-toolchain.toml', 'plrustc/.cargo/config.toml', '.github/workflows/ci.yml', '.cargo/config') }} - name: Start sccache server run: sccache --start-server && sccache --show-stats diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 8c51b287..f716b866 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -25,6 +25,22 @@ jobs: CI: true steps: + # If this workflow is being called from a schedule/cron job, then let's + # force the "develop" branch. Otherwise, use whatever is passed in via + # GITHUB_HEAD_REF. The result of this will be used below in the + # actions/checkout@vX step. Note that at the time of this writing, Github + # Actions does not allow us to specify which branch to run a schedule from + # (it always runs from the default branch, which in this case is master). + - name: Set up correct branch environment variable + run: | + if [ $GITHUB_EVENT_NAME == "schedule" ]; then + echo "Running via schedule, so using branch develop" + echo "NIGHTLY_BUILD_REF=develop" >> $GITHUB_ENV + else + echo "Not running via schedule, so using branch $GITHUB_HEAD_REF" + echo "NIGHTLY_BUILD_REF=$GITHUB_HEAD_REF" >> $GITHUB_ENV + fi + - uses: actions/checkout@v3 # The default installation of Docker on Github Actions runners are pretty outdated, as the artifact builder @@ -185,6 +201,22 @@ jobs: CI: true steps: + # If this workflow is being called from a schedule/cron job, then let's + # force the "develop" branch. Otherwise, use whatever is passed in via + # GITHUB_HEAD_REF. The result of this will be used below in the + # actions/checkout@vX step. Note that at the time of this writing, Github + # Actions does not allow us to specify which branch to run a schedule from + # (it always runs from the default branch, which in this case is master). + - name: Set up correct branch environment variable + run: | + if [ $GITHUB_EVENT_NAME == "schedule" ]; then + echo "Running via schedule, so using branch develop" + echo "NIGHTLY_BUILD_REF=develop" >> $GITHUB_ENV + else + echo "Not running via schedule, so using branch $GITHUB_HEAD_REF" + echo "NIGHTLY_BUILD_REF=$GITHUB_HEAD_REF" >> $GITHUB_ENV + fi + - uses: actions/checkout@v3 # The default installation of Docker on Github Actions runners are pretty outdated, as the artifact builder @@ -239,3 +271,93 @@ jobs: sleep 30 psql -h 127.0.0.1 -U postgres -c 'CREATE FUNCTION plrust.one() RETURNS INT LANGUAGE plrust AS $$ Ok(Some(1)) $$;' psql -h 127.0.0.1 -U postgres -c 'SELECT * FROM plrust.one()' + + plrust_macos_x86_64: + name: macos x86_64 tests + runs-on: ${{ matrix.os }} + if: "!contains(github.event.head_commit.message, 'nogha')" + + env: + PLRUST_TRUSTED_PGRX_OVERRIDE: "pgrx = { path = '/Users/runner/work/plrust/plrust/plrust-trusted-pgrx', package='plrust-trusted-pgrx' }" + + strategy: + matrix: + version: ["pg14"] + os: ["macos-12"] + target: ["host", "postgrestd"] + fail-fast: false + + steps: + # If this workflow is being called from a schedule/cron job, then let's + # force the "develop" branch. Otherwise, use whatever is passed in via + # GITHUB_HEAD_REF. The result of this will be used below in the + # actions/checkout@vX step. Note that at the time of this writing, Github + # Actions does not allow us to specify which branch to run a schedule from + # (it always runs from the default branch, which in this case is master). + - name: Set up correct branch environment variable + run: | + if [ $GITHUB_EVENT_NAME == "schedule" ]; then + echo "Running via schedule, so using branch develop" + echo "NIGHTLY_BUILD_REF=develop" >> $GITHUB_ENV + else + echo "Not running via schedule, so using branch $GITHUB_HEAD_REF" + echo "NIGHTLY_BUILD_REF=$GITHUB_HEAD_REF" >> $GITHUB_ENV + fi + + - uses: actions/checkout@v3 + + - name: Set up (Mac) prerequisites and environment + run: | + echo "" + + echo "----- Getting pre-installed Postgres major version -----" + PG_VER=$(pg_config --version | awk '{split($2,a,"."); print a[1]}') + echo "PG_VER=$PG_VER" >> $GITHUB_ENV + cat $GITHUB_ENV + + echo "----- Set up Postgres permissions -----" + sudo chmod a+rwx `$(which pg_config) --pkglibdir` `$(which pg_config) --sharedir`/extension + ls -lath `$(which pg_config) --pkglibdir` `$(which pg_config) --sharedir`/extension + echo "" + + echo "----- Output Cargo version -----" + cargo --version + echo "" + + echo "----- Outputting env -----" + env + echo "" + + # See /.github/scripts/install_cargo_pgrx.sh for more details + - name: Install cargo-pgrx defined in plrust/Cargo.toml + run: | + . $GITHUB_WORKSPACE/.github/scripts/install_cargo_pgrx.sh + install_cargo_pgrx + + - name: Install llvm-tools-preview + run: rustup component add llvm-tools-preview rustc-dev + + - name: Create protected files + run: | + sudo mkdir -p /var/ci-stuff/secret_rust_files + sudo echo "const FOO:i32 = 7;" /var/ci-stuff/secret_rust_files/const_foo.rs + sudo echo "const BAR:i32 = 8;" /var/ci-stuff/const_bar.rs + sudo chmod -R 600 /var/ci-stuff/secret_rust_files + if: matrix.target == 'postgrestd' + + - name: Test plrustc + run: cd plrustc && cargo test -p plrustc + + - name: Install plrustc + run: cd plrustc && ./build.sh && cp ../build/bin/plrustc ~/.cargo/bin + + - name: Run 'cargo pgrx init' against system-level ${{ matrix.version }} + run: cargo pgrx init --pg$PG_VER $(which pg_config) + + - name: Test PL/rust as "untrusted" + if: matrix.target == 'host' + run: cargo test --all --features "pg$PG_VER" --no-default-features + + - name: Test PL/rust as "trusted" (inc. postgrestd) + if: matrix.target == 'postgrestd' + run: cd plrust && STD_TARGETS="x86_64-apple-darwin-postgres" ./build && cargo test --verbose --no-default-features --features "pg$PG_VER trusted" diff --git a/doc/src/config-pg.md b/doc/src/config-pg.md index 0b7f50ec..5f96d724 100644 --- a/doc/src/config-pg.md +++ b/doc/src/config-pg.md @@ -107,11 +107,20 @@ This is the name of the linker `rustc` should use on for cross-compile. The architecture linker names have sensible defaults and shouldn't need to be be changed (unless the host is some esoteric Linux distribution we have not encountered yet). +Linux defaults: + ```bash plrust.x86_64_linker = 'x86_64_linux_gnu_gcc' plrust.aarch64_linker = 'aarch64_linux_gnu_gcc' ``` +macOS defaults: + +```bash +plrust.x86_64_linker = 'cc' +plrust.aarch64_linker = 'cc' +``` + #### `plrust.{arch}_pgrx_bindings_path` (string) diff --git a/doc/src/install-plrust.md b/doc/src/install-plrust.md index 94a0c6bd..672f95a8 100644 --- a/doc/src/install-plrust.md +++ b/doc/src/install-plrust.md @@ -39,11 +39,20 @@ uses `x86_64` and ensures the target is installed. If you are using `aarch64`, update the command accordingly. +Linux: + ```bash rustup component add llvm-tools-preview rustc-dev rustup target install x86_64-unknown-linux-gnu ``` +macOS: + +```bash +rustup component add llvm-tools-preview rustc-dev +rustup target install x86_64-apple-darwin +``` + Change into the `plrust/plrustc` directory to build `plrustc`. Move the generated binary into `~/.cargo/bin/`. @@ -115,6 +124,8 @@ Adding cross compilation support to PL/Rust requires a few minor changes to the the changes to make for cross compile support, not the full process. +#### Linux + As a Linux user with `sudo` access, install these additional prerequisites. @@ -132,14 +143,15 @@ rustup target install x86_64-unknown-linux-gnu ``` -Update the `STD_TARGETS` used when building `postgrestd` to include both architectures. -This step will take longer with cross compilation then only one architectures, as -it is required to double some of the work. +#### macOS + +The normal trusted install uses `rustup` to install one architecture target. +Cross compilation support requires both. ```bash -PG_VER=15 \ - STD_TARGETS="x86_64-postgres-linux-gnu aarch64-postgres-linux-gnu" \ - ./build +rustup component add llvm-tools-preview rustc-dev +rustup target install aarch64-apple-darwin +rustup target install x86_64-apple-darwin ``` > The above environment variables are the default... you can just run `./build`. `PG_VER=15` currently represents the latest released PostgreSQL version. diff --git a/plrust/build b/plrust/build index 0f34c0a5..2b81df5a 100755 --- a/plrust/build +++ b/plrust/build @@ -3,24 +3,48 @@ set -xe if [ -z "$STD_TARGETS" ]; then # if none specified, always build for these two targets - STD_TARGETS="x86_64-postgres-linux-gnu aarch64-postgres-linux-gnu" + if [ `uname` == "Darwin" ]; then + STD_TARGETS="x86_64-apple-darwin-postgres aarch64-apple-darwin-postgres" + else + STD_TARGETS="x86_64-postgres-linux-gnu aarch64-postgres-linux-gnu" + fi fi # and depending on the platform we're building on, we need to set a linker flag for the other # this'll get hairy when we support more platforms and we should port this script to Rust -if [ `uname -m` == "x86_64" ]; then - if [[ -z "$CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER" ]] && [[ -z "$CARGO_TARGET_AARCH64_POSTGRES_LINUX_GNU_LINKER" ]]; then - export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc - export CARGO_TARGET_AARCH64_POSTGRES_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc - fi -elif [ `uname -m` == "aarch64" ]; then - if [[ -z "$CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER" ]] && [[ -z "$CARGO_TARGET_X86_64_POSTGRES_LINUX_GNU_LINKER" ]]; then - export CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER=x86_64-linux-gnu-gcc - export CARGO_TARGET_X86_64_POSTGRES_LINUX_GNU_LINKER=x86_64-linux-gnu-gcc - fi + +if [ `uname` == "Darwin" ]; then + if [ `uname -m` == "arm64" ]; then + if [[ -z "$CARGO_TARGET_AARCH64_APPLE_DARWIN_LINKER" ]] && [[ -z "$CARGO_TARGET_AARCH64_APPLE_DARWIN_POSTGRES_LINKER" ]]; then + export CARGO_TARGET_AARCH64_APPLE_DARWIN_LINKER=cc + export CARGO_TARGET_AARCH64_APPLE_DARWIN_POSTGRES_LINKER=cc + fi + elif [ `uname -m` == "x86_64" ]; then + if [[ -z "$CARGO_TARGET_X86_64_APPLE_DARWIN_LINKER" ]] && [[ -z "$CARGO_TARGET_X86_64_APPLE_DARWIN_POSTGRES_LINKER" ]]; then + export CARGO_TARGET_X86_64_APPLE_DARWIN_LINKER=cc + export CARGO_TARGET_X86_64_APPLE_DARWIN_POSTGRES_LINKER=cc + fi + + else + echo unsupported macos build platform: $(uname -m) + exit 1 + fi + else - echo unsupported build platform: $(uname -m) - exit 1 + if [ `uname -m` == "x86_64" ]; then + if [[ -z "$CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER" ]] && [[ -z "$CARGO_TARGET_AARCH64_POSTGRES_LINUX_GNU_LINKER" ]]; then + export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc + export CARGO_TARGET_AARCH64_POSTGRES_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc + fi + elif [ `uname -m` == "aarch64" ]; then + if [[ -z "$CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER" ]] && [[ -z "$CARGO_TARGET_X86_64_POSTGRES_LINUX_GNU_LINKER" ]]; then + export CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER=x86_64-linux-gnu-gcc + export CARGO_TARGET_X86_64_POSTGRES_LINUX_GNU_LINKER=x86_64-linux-gnu-gcc + fi + else + echo unsupported build platform: $(uname -m) + exit 1 + fi fi # Make sure the tip of pgrx's develop branch is used, @@ -45,7 +69,7 @@ fi git clone https://github.com/tcdi/postgrestd.git --branch "rust-1.70.0" --recurse-submodules cd ./postgrestd fi - rm --force rust-toolchain.toml + rm -f rust-toolchain.toml STD_TARGETS="$STD_TARGETS" ./run clean STD_TARGETS="$STD_TARGETS" ./run install ) diff --git a/plrust/src/lib.rs b/plrust/src/lib.rs index 3da2034b..7520d5d4 100644 --- a/plrust/src/lib.rs +++ b/plrust/src/lib.rs @@ -12,10 +12,17 @@ Use of this source code is governed by the PostgreSQL license that can be found #[cfg(all( feature = "trusted", - not(all( - target_os = "linux", - any(target_arch = "x86_64", target_arch = "aarch64") - )) + not(any( + all( + target_os = "linux", + any(target_arch = "x86_64", target_arch = "aarch64") + ), + all( + target_os = "macos", + any(target_arch = "x86_64", target_arch = "aarch64") + ) + ) + ) ))] compile_error!("This platform does not support the 'trusted' version of plrust"); diff --git a/plrust/src/target.rs b/plrust/src/target.rs index fd0e3262..71411c70 100644 --- a/plrust/src/target.rs +++ b/plrust/src/target.rs @@ -34,7 +34,13 @@ mod host { #[allow(non_snake_case)] const fn VENDOR() -> &'static str { if crate::TRUSTED { - "postgres" + cfg_if::cfg_if! { + if #[cfg(target_vendor = "apple")] { + "apple-darwin" + } else { + "postgres" + } + } } else { cfg_if::cfg_if! { if #[cfg(target_vendor = "apple")] { @@ -48,11 +54,15 @@ mod host { } } - cfg_if::cfg_if! { if #[cfg(target_os = "macos")] { - const OS: &str = "darwin"; - } else { - const OS: &str = std::env::consts::OS; - }} + cfg_if::cfg_if! { + if #[cfg(all(feature = "trusted", target_os = "macos"))] { + const OS: &str = "postgres"; + } else if #[cfg(target_os = "macos")] { + const OS: &str = "darwin"; + } else { + const OS: &str = std::env::consts::OS; + } + } pub(super) fn target_tuple() -> String { let tuple = [ARCH, VENDOR(), OS, ENV]; @@ -148,9 +158,18 @@ impl CrossCompilationTarget { self.target().as_str().to_uppercase().replace('-', "_") ); - let linker = gucs::get_linker_for_target(self).unwrap_or_else(|| match self { - CrossCompilationTarget::X86_64 => "x86_64-linux-gnu-gcc".into(), - CrossCompilationTarget::Aarch64 => "aarch64-linux-gnu-gcc".into(), + let linker = gucs::get_linker_for_target(self).unwrap_or_else(|| { + #[cfg(target_os = "macos")] + match self { + CrossCompilationTarget::X86_64 => "cc".into(), + CrossCompilationTarget::Aarch64 => "cc".into(), + } + + #[cfg(target_os = "linux")] + match self { + CrossCompilationTarget::X86_64 => "x86_64-linux-gnu-gcc".into(), + CrossCompilationTarget::Aarch64 => "aarch64-linux-gnu-gcc".into(), + } }); (key, linker) @@ -182,7 +201,17 @@ impl TryFrom<&str> for CrossCompilationTarget { impl From for CompilationTarget { fn from(cct: CrossCompilationTarget) -> Self { cfg_if::cfg_if! { - if #[cfg(feature = "trusted")] { + if #[cfg(all(feature = "trusted", target_os = "macos"))] { + match cct { + CrossCompilationTarget::X86_64 => "x86_64-apple-darwin-postgres", + CrossCompilationTarget::Aarch64 => "aarch64-apple-darwin-postgres", + }.into() + } else if #[cfg(target_os = "macos")] { + match cct { + CrossCompilationTarget::X86_64 => "x86_64-apple-darwin", + CrossCompilationTarget::Aarch64 => "aarch64-apple-darwin", + }.into() + } else if #[cfg(feature = "trusted")] { match cct { CrossCompilationTarget::X86_64 => "x86_64-postgres-linux-gnu", CrossCompilationTarget::Aarch64 => "aarch64-postgres-linux-gnu",