Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 77 additions & 23 deletions crates/cargo-wdk/src/actions/build/build_task.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,9 @@ use std::path::{Path, PathBuf};
use anyhow::Result;
use mockall_double::double;
use tracing::{debug, info};
use wdk_build::utils::{PathExt, StripExtendedPathPrefixError};

#[double]
use crate::providers::{exec::CommandExec, fs::Fs};
use crate::providers::exec::CommandExec;
use crate::{
actions::{build::error::BuildTaskError, to_target_triple, Profile, TargetArch},
trace,
Expand All @@ -30,47 +29,42 @@ pub struct BuildTask<'a> {
}

impl<'a> BuildTask<'a> {
/// Creates a new instance of `BuildTask`
/// Creates a new instance of `BuildTask`.
///
/// # Arguments
/// * `package_name` - The name of the package to build
/// * `working_dir` - The working directory for the build
/// * `profile` - An optional profile for the build
/// * `target_arch` - The target architecture for the build
/// * `verbosity_level` - The verbosity level for logging
/// * `command_exec` - The command execution provider
/// * `fs` - The file system provider
///
/// # Returns
/// * `Result<Self, BuildTaskError>` - A result containing the new instance
/// of `BuildTask` or an error
/// # Errors
/// * `BuildTaskError::CanonicalizeManifestPath` - If there is an IO error
/// while canonicalizing the working dir
/// * `BuildTaskError::EmptyManifestPath` - If the manifest path is empty
/// * `Self` - A new instance of `BuildTask`.
///
/// # Panics
/// * If `working_dir` is not absolute
pub fn new(
package_name: &'a str,
working_dir: &'a Path,
profile: Option<&'a Profile>,
target_arch: TargetArch,
verbosity_level: clap_verbosity_flag::Verbosity,
command_exec: &'a CommandExec,
fs: &'a Fs,
) -> Result<Self, BuildTaskError> {
let manifest_path = fs.canonicalize_path(&working_dir.join("Cargo.toml"))?;
let manifest_path = match manifest_path.strip_extended_length_path_prefix() {
Ok(path) => path,
Err(StripExtendedPathPrefixError::NoExtendedPathPrefix) => manifest_path,
Err(StripExtendedPathPrefixError::EmptyPath) => {
return Err(BuildTaskError::EmptyManifestPath);
}
};
Ok(Self {
) -> Self {
assert!(
working_dir.is_absolute(),
"Working directory path must be absolute. Input path: {}",
working_dir.display()
);
Self {
package_name,
profile,
target_arch,
verbosity_level,
manifest_path,
manifest_path: working_dir.join("Cargo.toml"),
command_exec,
})
}
}

/// Entry point method to run the build task
Expand Down Expand Up @@ -111,3 +105,63 @@ impl<'a> BuildTask<'a> {
Ok(())
}
}

#[cfg(test)]
mod tests {
use wdk_build::CpuArchitecture;

use super::*;
use crate::actions::{Profile, TargetArch};

#[test]
fn new_succeeds_for_valid_args() {
let working_dir = PathBuf::from("C:/absolute/path/to/working/dir");
let package_name = "test_package";
let profile = Profile::Dev;
let target_arch = TargetArch::Selected(CpuArchitecture::Amd64);
let verbosity_level = clap_verbosity_flag::Verbosity::default();
let command_exec = CommandExec::new();

let build_task = BuildTask::new(
package_name,
&working_dir,
Some(&profile),
target_arch,
verbosity_level,
&command_exec,
);

assert_eq!(build_task.package_name, package_name);
assert_eq!(build_task.profile, Some(&profile));
assert_eq!(build_task.target_arch, target_arch);
assert_eq!(build_task.manifest_path, working_dir.join("Cargo.toml"));
assert_eq!(
std::ptr::from_ref(build_task.command_exec),
&raw const command_exec,
"CommandExec instances are not the same"
);
// TODO: Add assert for verbosity_level once `clap-verbosity-flag` crate
// is updated to 3.0.4
}

#[test]
#[should_panic(expected = "Working directory path must be absolute. Input path: \
relative/path/to/working/dir")]
fn new_panics_when_working_dir_is_not_absolute() {
let working_dir = PathBuf::from("relative/path/to/working/dir");
let package_name = "test_package";
let profile = Some(Profile::Dev);
let target_arch = TargetArch::Selected(CpuArchitecture::Amd64);
let verbosity_level = clap_verbosity_flag::Verbosity::default();
let command_exec = CommandExec::new();

BuildTask::new(
package_name,
&working_dir,
profile.as_ref(),
target_arch,
verbosity_level,
&command_exec,
);
}
}
4 changes: 3 additions & 1 deletion crates/cargo-wdk/src/actions/build/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// License: MIT OR Apache-2.0
//! This module defines error types used in the build action module.

use std::{path::PathBuf, string::FromUtf8Error};
use std::{io, path::PathBuf, string::FromUtf8Error};

use thiserror::Error;

Expand All @@ -11,6 +11,8 @@ use crate::providers::error::{CommandError, FileError};
/// Errors for the build action layer
#[derive(Error, Debug)]
pub enum BuildActionError {
#[error("Provided path is not absolute: {0}")]
NotAbsolute(PathBuf, #[source] io::Error),
#[error(transparent)]
WdkBuildConfig(#[from] wdk_build::ConfigError),
#[error("Error Parsing Cargo.toml, not a valid rust project/workspace")]
Expand Down
63 changes: 32 additions & 31 deletions crates/cargo-wdk/src/actions/build/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ mod package_task;
#[cfg(test)]
mod tests;
use std::{
path::{Path, PathBuf},
path::{absolute, Path, PathBuf},
result::Result::Ok,
};

Expand Down Expand Up @@ -57,31 +57,33 @@ pub struct BuildAction<'a> {
}

impl<'a> BuildAction<'a> {
/// Creates a new instance of `BuildAction`
/// # Arguments
/// Creates a new instance of `BuildAction`.
///
/// # Arguments:
/// * `params` - The `BuildActionParams` struct containing the parameters
/// for the build action
/// * `wdk_build` - The WDK build provider instance
/// * `command_exec` - The command execution provider instance
/// * `fs` - The file system provider instance
/// * `metadata` - The metadata provider instance
///
/// # Returns
/// * `Result<Self>` - A result containing the new instance of `BuildAction`
/// or an error
/// * `Result<Self>` - A result containing either a new instance of
/// `BuildAction` on success, or an `anyhow::Error`.
///
/// # Errors
/// * `BuildActionError::IoError` - If there is an IO error while
/// canonicalizing the working dir
/// * [`anyhow::Error`] - If `params.working_dir` is not a syntactically
/// valid path, e.g. it is empty
pub fn new(
params: &BuildActionParams<'a>,
wdk_build: &'a WdkBuild,
command_exec: &'a CommandExec,
fs: &'a Fs,
metadata: &'a Metadata,
) -> Result<Self> {
// TODO: validate and init attrs here
let working_dir = fs.canonicalize_path(params.working_dir)?;
// TODO: validate params
Ok(Self {
working_dir,
working_dir: absolute(params.working_dir)?,
profile: params.profile,
target_arch: params.target_arch,
verify_signature: params.verify_signature,
Expand Down Expand Up @@ -127,10 +129,10 @@ impl<'a> BuildAction<'a> {
"Initialized build for project at: {}",
self.working_dir.display()
);
wdk_build::cargo_make::setup_path()?;
debug!("PATH env variable is set with WDK bin and tools paths");
let build_number = self.wdk_build.detect_wdk_build_number()?;
debug!("WDK build number: {}", build_number);
wdk_build::cargo_make::setup_path()?;
debug!("PATH env variable is set with WDK bin and tools paths");

// Standalone driver/driver workspace support
if self.fs.exists(&self.working_dir.join("Cargo.toml")) {
Expand Down Expand Up @@ -217,17 +219,21 @@ impl<'a> BuildAction<'a> {
Ok(())
}

// Method to initiate the build and package process for the given working
// Method to initiate the build and package tasks for the given working
// directory and the cargo metadata
fn run_from_workspace_root(&self, working_dir: &Path) -> Result<(), BuildActionError> {
let cargo_metadata = &self.get_cargo_metadata(working_dir)?;
let target_directory = cargo_metadata.target_directory.as_std_path().to_path_buf();
let wdk_metadata = Wdk::try_from(cargo_metadata);
let workspace_packages = cargo_metadata.workspace_packages();
let workspace_root = self
.fs
.canonicalize_path(cargo_metadata.workspace_root.clone().as_std_path())?;
if workspace_root.eq(working_dir) {
let workspace_root =
absolute(cargo_metadata.workspace_root.as_std_path()).map_err(|e| {
BuildActionError::NotAbsolute(cargo_metadata.workspace_root.clone().into(), e)
})?;
let target_directory =
absolute(cargo_metadata.target_directory.as_std_path()).map_err(|e| {
BuildActionError::NotAbsolute(cargo_metadata.target_directory.clone().into(), e)
})?;
if workspace_root.eq(&working_dir) {
// If the working directory is root of a standalone project or a
// workspace
debug!(
Expand All @@ -242,7 +248,8 @@ impl<'a> BuildAction<'a> {
.expect("Unable to find package path from Cargo manifest path")
.into();

let package_root_path = self.fs.canonicalize_path(package_root_path.as_path())?;
let package_root_path = absolute(package_root_path.as_path())
.map_err(|e| BuildActionError::NotAbsolute(package_root_path.clone(), e))?;
debug!(
"Processing workspace member package: {}",
package_root_path.display()
Expand Down Expand Up @@ -286,15 +293,10 @@ impl<'a> BuildAction<'a> {
.parent()
.expect("Unable to find package path from Cargo manifest path")
.into();
self.fs
.canonicalize_path(package_root_path.as_path())
.is_ok_and(|package_root_path| {
debug!(
"Processing workspace member package: {}",
package_root_path.display()
);
package_root_path.eq(working_dir)
})
absolute(package_root_path.as_path()).is_ok_and(|p| {
debug!("Processing workspace member package: {}", p.display());
p.eq(&working_dir)
})
});

let package = package
Expand Down Expand Up @@ -352,8 +354,7 @@ impl<'a> BuildAction<'a> {
self.target_arch,
self.verbosity_level,
self.command_exec,
self.fs,
)?
)
.run()?;

let wdk_metadata = if let Ok(wdk_metadata) = wdk_metadata {
Expand Down Expand Up @@ -425,7 +426,7 @@ impl<'a> BuildAction<'a> {
self.wdk_build,
self.command_exec,
self.fs,
)?
)
.run()?;

info!("Processing completed for package: {}", package_name);
Expand Down
Loading
Loading