Skip to content

Commit

Permalink
update pipeline to run sample projects; add multi file sample (#1040)
Browse files Browse the repository at this point in the history
This PR updates our samples build stage in the pipeline to accept
projects. We detect if a sample is a project in `build.py` and execute
the correct `qsc` command accordingly.

Additionally, this PR adds a new command line flag to `qsc` and `qsi`:
`--qsharp-json`. This flag allows the user to specify a path to a
`qsharp.json` to compile a project via the command line. Previously, the
only way to compile a project via the command line was to `cd` into it.
  • Loading branch information
sezna authored Jan 19, 2024
1 parent 9c66e72 commit ff95d99
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 6 deletions.
13 changes: 12 additions & 1 deletion build.py
Original file line number Diff line number Diff line change
Expand Up @@ -317,17 +317,28 @@ def step_end():

if build_samples:
step_start("Building qsharp samples")
project_directories = [dir for dir in os.walk(samples_src) if "qsharp.json" in dir[2]]
single_file_directories = [candidate for candidate in os.walk(samples_src) if all([not proj_dir[0] in candidate[0] for proj_dir in project_directories])]

files = [
os.path.join(dp, f)
for dp, _, filenames in os.walk(samples_src)
for dp, _, filenames in single_file_directories
for f in filenames
if os.path.splitext(f)[1] == ".qs"
]
projects = [
os.path.join(dp, f)
for dp, _, filenames in project_directories
for f in filenames
if f == "qsharp.json"
]
cargo_args = ["cargo", "run", "--bin", "qsc"]
if build_type == "release":
cargo_args.append("--release")
for file in files:
subprocess.run((cargo_args + ["--", file]), check=True, text=True, cwd=root_dir)
for project in projects:
subprocess.run((cargo_args + ["--", "--qsharp-json", project]), check=True, text=True, cwd=root_dir)
step_end()

if build_npm:
Expand Down
6 changes: 5 additions & 1 deletion compiler/qsc/src/bin/qsc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ struct Cli {
/// Q# source files to compile, or `-` to read from stdin.
#[arg()]
sources: Vec<PathBuf>,

/// Path to a Q# manifest for a project
#[arg(short, long)]
qsharp_json: Option<PathBuf>,
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, ValueEnum)]
Expand Down Expand Up @@ -83,7 +87,7 @@ fn main() -> miette::Result<ExitCode> {

if sources.is_empty() {
let fs = StdFs;
let manifest = Manifest::load()?;
let manifest = Manifest::load(cli.qsharp_json)?;
if let Some(manifest) = manifest {
let project = fs.load_project(&manifest)?;
let mut project_sources = project.sources;
Expand Down
6 changes: 5 additions & 1 deletion compiler/qsc/src/bin/qsi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ struct Cli {
/// Exit after loading the files or running the given file(s)/entry on the command line.
#[arg(long)]
exec: bool,

/// Path to a Q# manifest for a project
#[arg(short, long)]
qsharp_json: Option<PathBuf>,
}

struct TerminalReceiver;
Expand Down Expand Up @@ -78,7 +82,7 @@ fn main() -> miette::Result<ExitCode> {

if sources.is_empty() {
let fs = StdFs;
let manifest = Manifest::load()?;
let manifest = Manifest::load(cli.qsharp_json)?;
if let Some(manifest) = manifest {
let project = fs.load_project(&manifest)?;
let mut project_sources = project.sources;
Expand Down
21 changes: 18 additions & 3 deletions compiler/qsc_project/src/manifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,16 +46,31 @@ impl Manifest {
/// a manifest file exists but is the wrong format.
/// Returns `Ok(None)` if there is no file matching the manifest file
/// name.
pub fn load() -> std::result::Result<Option<ManifestDescriptor>, Error> {
let current_dir = current_dir()?;
Self::load_from_path(current_dir)
pub fn load(
manifest_path: Option<PathBuf>,
) -> std::result::Result<Option<ManifestDescriptor>, Error> {
let dir = match manifest_path {
Some(path) => path,
None => current_dir()?,
};
Self::load_from_path(dir)
}

/// Given a [PathBuf], traverse [PathBuf::ancestors] until a Manifest is found.
/// Returns [None] if no manifest named [MANIFEST_FILE_NAME] is found.
/// Returns an error if a manifest is found, but is not parsable into the
/// expected format.
pub fn load_from_path(path: PathBuf) -> std::result::Result<Option<ManifestDescriptor>, Error> {
// if the given path points to a file, change it to point to the parent folder.
// This lets consumers pass in either the path directly to the manifest file, or the path
// to the folder containing the manifest file.
let path = if path.is_file() {
let mut path = path;
path.pop();
path
} else {
path
};
let ancestors = path.ancestors();
for ancestor in ancestors {
let listing = ancestor.read_dir()?;
Expand Down
1 change: 1 addition & 0 deletions samples/language/MultiFileProject/qsharp.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
19 changes: 19 additions & 0 deletions samples/language/MultiFileProject/src/Main.qs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/// # Sample
/// Multi File Project
///
/// # Description
/// Organizing code into multiple Q# source files is an important part of
/// writing readable and maintainable code. In this project, we have `Main.qs`,
/// and `Particle.qs`, which defines a new namespace for particle operations.
/// The presence of a Q# manifest file (`qsharp.json`) tells the compiler
/// to include all Q# files under `src/`.
namespace MyQuantumApp {
open Particle;
@EntryPoint()
operation Main() : Unit {
let particleA = Particle(0, 0, 0);
let particleB = Particle(1, 1, 1);

let particleC = addParticles(particleA, particleB);
}
}
9 changes: 9 additions & 0 deletions samples/language/MultiFileProject/src/Particle.qs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace Particle {
newtype Particle = (x: Int, y: Int, z: Int);

function addParticles(a: Particle, b: Particle) : Particle {
let (x1, y1, z1) = a!;
let (x2, y2, z2) = b!;
return Particle(x1 + x2, y1 + y2, z1 + z2);
}
}

0 comments on commit ff95d99

Please sign in to comment.