Skip to content

Commit

Permalink
experiment: a cross-target package for establishing cross-compilati…
Browse files Browse the repository at this point in the history
…on targets
  • Loading branch information
dherman committed Apr 1, 2023
1 parent 0ec5350 commit 2b399a4
Show file tree
Hide file tree
Showing 19 changed files with 2,801 additions and 192 deletions.
38 changes: 38 additions & 0 deletions .github/workflows/cross.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: cargo-cp-artifact

on:
push:
# Prevent duplicate runs of this workflow on our own internal PRs.
branches:
- main
- next/*
pull_request:
types: [opened, synchronize, reopened, labeled]
branches:
- main
- next/*

jobs:
matrix:
runs-on: ubuntu-latest
outputs:
includes: ${{ steps.define.includes }}
steps:
- name: Define Cross-Compilation Target Matrix
id: define
uses: dherman/target-matrix@v1
with:
toolchain: rust
windows-latest: x86_64-pc-windows-msvc
macos-latest: x86_64-apple-darwin
ubuntu-latest: x86_64-unknown-linux-gnu x86_64-unknown-freebsd x86_64-unknown-openbsd

build:
needs: matrix
runs-on: ${{ matrix.os }}
strategy:
matrix:
includes: ${{ needs.matrix.includes }}
steps:
- name: Show Target
run: echo "${{ matrix.target }}"
1 change: 1 addition & 0 deletions crates/cargo-cp-artifact/src/bin.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
mod artifact;
mod cargo;
mod cli;
mod copy;

use cargo::Status;

Expand Down
117 changes: 23 additions & 94 deletions crates/cargo-cp-artifact/src/cargo.rs
Original file line number Diff line number Diff line change
@@ -1,67 +1,10 @@
use crate::artifact::{Artifact, ArtifactError, ArtifactKind};

use cargo_metadata::{Message, Target};
use std::collections::HashMap;
use std::path::Path;
use std::process::{Command, Stdio};

#[derive(Debug, PartialEq, Eq)]
pub struct CopyMap(HashMap<Artifact, Vec<String>>);

impl CopyMap {
pub fn new() -> Self {
Self(HashMap::new())
}

pub fn add(&mut self, kind: ArtifactKind, crate_name: String, output_file: String) {
let key = Artifact { kind, crate_name };

if !self.0.contains_key(&key) {
let _ = self.0.insert(key, vec![output_file]);
} else {
self.0.get_mut(&key).unwrap().push(output_file);
}
}

pub fn copy(&self, artifact: &Artifact, from: &Path) -> Result<(), CargoError> {
if let Some(output_files) = self.0.get(&artifact) {
for output_file in output_files {
artifact
.copy(from, Path::new(output_file))
.map_err(CargoError::ArtifactCopyFailed)?;
}
}
Ok(())
}
}

#[cfg(test)]
impl CopyMap {
pub fn set(&mut self, artifact: Artifact, output_files: &[&str]) {
let _ = self.0.insert(
artifact,
output_files.iter().map(|s| s.to_string()).collect(),
);
}
}

#[derive(Debug, PartialEq, Eq)]
pub struct CargoCommand {
pub artifacts: CopyMap,
pub command: String,
pub args: Vec<String>,
}

pub enum Status {
Success,
Failure,
}
use cargo_metadata::{Message, MessageIter};
use std::io::BufReader;
use std::process::{Command, Stdio, Child, ChildStdout};

pub enum CargoError {
SpawnFailed(std::io::Error),
MessageParseFailed(std::io::Error),
CommandWaitFailed(std::io::Error),
ArtifactCopyFailed(ArtifactError),
}

impl std::fmt::Display for CargoError {
Expand All @@ -73,51 +16,37 @@ impl std::fmt::Display for CargoError {
CargoError::MessageParseFailed(err) => {
write!(f, "Could not read command output: {}", err)
}
CargoError::CommandWaitFailed(err) => {
write!(f, "Command failed to exit: {}", err)
}
CargoError::ArtifactCopyFailed(err) => {
write!(f, "Failed to copy artifact: {}", err)
}
}
}
}

#[derive(Debug, PartialEq, Eq)]
pub struct CargoCommand {
pub command: String,
pub args: Vec<String>,
}

pub enum Status {
Success,
Failure,
}

pub type CargoStream = MessageIter<BufReader<ChildStdout>>;

impl CargoCommand {
pub fn new(artifacts: CopyMap, command: String, args: Vec<String>) -> Self {
Self {
artifacts,
command,
args,
}
pub fn new(command: String, args: Vec<String>) -> Self {
Self { command, args }
}

pub fn exec(self) -> Result<(), CargoError> {
let mut command = Command::new(self.command)
pub fn spawn(self) -> Result<(Child, CargoStream), CargoError> {
let mut child = Command::new(self.command)
.args(&self.args)
.stdout(Stdio::piped())
.spawn()
.map_err(CargoError::SpawnFailed)?;

let reader = std::io::BufReader::new(command.stdout.take().unwrap());
for message in cargo_metadata::Message::parse_stream(reader) {
let message = message.map_err(CargoError::MessageParseFailed)?;
if let Message::CompilerArtifact(artifact) = message {
let Target {
kind: kinds, name, ..
} = artifact.target;
for (kind, filename) in kinds.iter().zip(artifact.filenames) {
let from = filename.into_std_path_buf();
if let Some(kind) = ArtifactKind::parse(kind) {
let crate_name = name.clone();
let artifact = Artifact { kind, crate_name };
self.artifacts.copy(&artifact, &from)?;
}
}
}
}

command.wait().map_err(CargoError::CommandWaitFailed)?;
Ok(())
let reader = BufReader::new(child.stdout.take().unwrap());
let stream = Message::parse_stream(reader);
Ok((child, stream))
}
}
Loading

0 comments on commit 2b399a4

Please sign in to comment.