cargo rust build script - print output of command - rust

I am new to rust and cargo, and I am trying to do something very simple!
I have something like this (in build.rs):
use std::process::Command;
fn main() {
Command::new("echo 123");
}
And I want to see the output of the command echo 123. I want 123 to get printed to the build output (this is mostly to debug what I am doing) and wont be part of the final project.
I have tried cargo build --verbose - this does not work.
I can't extrapolate an answer from there posts (and some others like it):
https://github.com/rust-lang/cargo/issues/985
https://github.com/rust-lang/cargo/issues/1106
I feel this must be simple to do - but I have been stuck for hours looking on the web and not finding the answer.

Just building a Command with Command::new does not execute it yet. It just starts a builder pattern. To actually execute it, you have to use the methods spawn, output or status. Example:
Command::new("echo")
.arg("123")
.spawn()
.expect("failed to spawn process");
It's very unfortunate that this doesn't produce a warning. Someone recently tried to add the #[must_use] attribute to Command, which would make your code procude a warning. The PR closed for now but it seems like it will be added eventually.

We can use a macro and it worked form me, but there is a warning, since it uses cargo to display. but that is fine for me.
I found below code from git hub discussion:
Cargo doesn’t display output from a command in build.rs #985
macro_rules! p {
($($tokens: tt)*) => {
println!("cargo:warning={}", format!($($tokens)*))
}
}
fn main() {
p!("BUILD.rs -> Starting ...");
}

Related

Where do I need to put file to be read by Rust?

When I was reading through the tutorial for Rust here (https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html). I found this block of code:
use std::fs::File;
fn main() {
let f = File::open("hello.txt");
let f = match f {
Ok(file) => file,
Err(error) => panic!("Problem opening the file: {:?}", error),
};
}
It always displays an error: { code: 2, kind: NotFound, message: "The system cannot find the file specified." } even when I make a hello.txt at the root folder of the src, it fails to read it.
In another example here, I use cargo run to no success. The program still fails to read hello.txt file. I'm aware that the example uses rustc open.rs && ./open. Since I don't understand why is it suddenly use different compile method and what's it even mean... I just kinda skip it and try to use cargo run instead
Where do I need to put my file here so cargo run can read it ?
Also if I run the production code and need the program to read an external file, where do I need to put it ?
Here's my folder structure. Pretty simple since I just start to learn RUST.
Thank you in advance.
A file without a directory component in the name needs to be in the current working directory, i.e. the directory from which you start your executable or cargo run.
If you start cargo from an IDE, it might not be immediately apparent what directory it will use as the current directory. In that case, you can always find the current working directory by printing it explicitly:
fn main() {
println!("{}", std::env::current_dir().unwrap().display())
}

How to enable unstable Rust feature str_split_once?

I'm having a hard time figuring out where do I need to write something to enable this feature.
I tried adding #![feature(str_split_once)] to the file where I'm using it but nothing happens. By Googling I found How do you enable a Rust "crate feature"? but after adding
[features]
default = ["str_split_once"]
to Cargo it doesn't build with
Caused by: feature default includes str_split_once which is
neither a dependency nor another feature
I tried adding #![feature(str_split_once)] to the file where I'm using it but nothing happens.
I guess there's not really "nothing happens", but there was a warning similar to this one:
warning: crate-level attribute should be in the root module
--> src/lib.rs:2:5
|
2 | #![feature(str_split_once)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
Playground
Just add this line at the beginning of lib.rs and/or main.rs, build with nightly, and it should work:
#![feature(str_split_once)]
fn main() {
// prints Some(("test1", "test2 test3"))
println!("{:?}", "test1 test2 test3".split_once(" "));
}
Playground

Getting error " not enough arguments in call to s.statsd.SendLoop" when running "go build" command

I'm trying to run go build command for my project but it exits with below error.
alpha#GHOST-RIDER:~/GoWorkspace/src/github.com/hyperledger/firstproject$ go build
# github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/core/operations
../fabric-sdk-go/internal/github.com/hyperledger/fabric/core/operations/system.go:227:23: not enough arguments in call to s.statsd.SendLoop
have (<-chan time.Time, string, string)
want (context.Context, <-chan time.Time, string, string)
Any help would be appreciated.
As per code fabric is using the different version of this library: github.com/go-kit/kit/metrics/statsd. If you follow the System struct's statsd attribute, you can reach the reference on imports.
In master branch of this lib, SendLoop function requires 4 attributes, so that's the root cause. So this causes error when you compile on your local environment.
I had the same issue and worked around it by checking out a tag of library as below:
cd $GOPATH/src/github.com/go-kit/kit
git fetch --tags
git checkout v0.8.0
found a solution on the hyperledger-fabric-go-sdk group chat.
Add context.Background() in s.statsd.SendLoop like below
s.statsd.SendLoop(context.Background(), s.sendTicker.C, network, address)
in fabric-sdk-go/internal/github.com/hyperledger/fabric/core/operations/system.go file at line 227.
I had a same issue, my solution worked and don't need edit fabric source code.
specify github.com/go-kit/kit to v0.8.0, modify go.mod:
replace github.com/go-kit/kit => github.com/go-kit/kit v0.8.0 // you specific version
require (
... ...
// Maybe other version, go mod tidy update automatically, don't care it.
github.com/go-kit/kit v0.9.0 // indirect
... ...
)
then it worked.

How do I build code in a documentation test but not run it?

I have code in my documentation that can only be run if the user has some software on their machine. To emulate this, I add panic! to the sample code:
//!```rust
//!fn main() {
//! panic!("Not run me");
//!}
//!```
#[cfg(test)]
mod tests {
#[test]
fn it_works() {}
}
I want to check that the code in the comments can be compiled, but I do not want it to be run during cargo test. Right now, I get:
running 1 test
test src/lib.rs - (line 1) ... FAILED
failures:
---- src/lib.rs - (line 1) stdout ----
thread 'rustc' panicked at 'test executable failed:
thread 'main' panicked at 'Not run me', <anon>:2
note: Run with `RUST_BACKTRACE=1` for a backtrace.
I read about doctest = false, but that disables not only the running of code in comments, but also syntax checking the code in comments.
How can I only disable running of code in comments, but still enable compilation of code in comments during cargo test?
There are several annotations you can use to change how the Rust code is processed. See the test documentation.
In your case it sounds like no_run is the one you'd want
//!```rust,no_run
//!fn main() {
//! panic!("Not run me");
//!}
//!```
Alternatively you could use should_panic so Rust will run the code, but expect the panic. If it's code that won't actually compile, you can use ignore.

Groovy Postbuild do not execute scripts on Jenkins

I've written simple groovy script, but I don't know how to execute it on Jenkins.
Look at this simple script:
String jbN = System.getenv('JOB_NAME')
println jbN
println "Hello"
I would except that I will reveived at least "Hello". Script give no return. I've just received Build step 'Groovy Postbuild' marked build as failure(or success)
It seems that script is not executed.
EDIT:
I didn't add it, but I have already script which will analize logs, so I need it to execute it post-build.
The problem is bigger then I thought. Plugins: "Scriptler" or "Groovy Plugin" do not print anything.
Script which I'm trying to print out:
String jbN = System.getenv('JOB_NAME')
println jbN
I found the solution:
Script was executed but wasn't printed to console output.
To print result to console output you need to write:
manager.listener.logger.println("Some string") instead of println.
To make it shorter do:
logger = manager.listener.logger.&println
// and call like this:
logger("test log message")
EDIT: add in logger example and to describe how to get env vars (and how to not get them) and to hopefully save people some debugging time . . . this is simple but awkward stuff.
To get the workspace you can go through the manager object. Like this:
manager.build.workspace
To get env vars, this does not work:
String jbN = System.getenv('JOB_NAME')
It shows jbN is null.
That makes sense as JOB_NAME is not an actual system environment var.
This also does not work to get env vars, an exception is thrown:
${manager.envVars['WORKSPACE']}
This does work to get jenkins job "env vars" like WORKSPACE, JOB_NAME, BUILD_NAME:
def build = Thread.currentThread().executable
workspace = build.getEnvVars()["WORKSPACE"]
Example of use, you can call a groovy script in workspace like this:
evaluate(new File(manager.build.workspace.toString() + "/dirinworkspace/scriptname.groovy"))
In your case you want to use the Groovy plugin rather than the Groovy Postbuild plugin.
The Groovy Postbuild plugin is made to change the build result (postbuild).
The Groovy plugin is made to run simple Groovy scripts inside your job.
Click Manage Jenkins-->Script Console

Resources