Compiler outputs the errors under Wine, but not on Windows - windows

I've got .mqh source code file with syntax error, for example created by the following command:
echo some_error > fail.mqh
Now, I'm using Metaeditor compiler to check the syntax and my goal is to print the errors to the standard output (CON), instead of logging them to the file (/log:file.log). See: Compiling.
The following syntax works fine on Linux/macOS as follow (also under wine cmd.exe):
$ wine metaeditor.exe /s /log:CON /compile:fail.mqh
??fail.mqh : information: Checking 'fail.mqh'
fail.mqh(1,1) : error 116: 'some_error' - declaration without type
fail.mqh(1,1) : error 161: 'some_error' - unexpected end of program
: information: Result 2 error(s), 0 warning(s)
Please note that the /log parameter is required, otherwise the compiler doesn't print anything by default. So if /log is specified, then by default it logs the compilation result to the file. And I'm using special CON device to display the errors.
The problem is when I'm running the same command on Windows (cmd), then I've got no output:
> metaeditor.exe /s /log:CON /compile:fail.mqh
Same for CON:/con: as well. Also on PowerShell.
Although CON works for echo, e.g.: echo test > CON.
I could assume it could be a bug of the compiler, but then it works fine under Wine. Why would this work only under Wine?
Is there another way of outputting the errors to the terminal screen on Windows, instead of log file?
Note: You can install compiler from the site or download the binary (32bit or 64bit) to test above.
Clarification: My main blocker for using two separate commands (compile and print the error log after that) is that CI test may fail before the errors are printed, which makes the tests useless and it's a story for another question. So my goal is to check the syntax and print the errors at one go.

According to Support Team, Metaeditor application does not have a console, so it cannot output logs to the screen. So it seems wine handles special CON device differently. I've reported the issue to the Service Desk and it's still open, so they may implement the console support in the future.
Currently the only workaround is to use type command for output log file to console after compiling the files (or emulate it under wine). Even if the compiler could display it to the console, it won't work properly with CI either (in terms of handling the error codes), because logic of return exit of metaeditor.exe is completely broken as it returns the number of successfully compiled files instead of the error code (e.g. if you compile 20 files, you'll get 20 error code?!)! So relying on return exit of metaeditor.exe is a mistake and MQL team isn't planning to fix it anyway, since they say this is how it should work in their opinion.

Related

How to tell if a program is installed on Linux in Haskell

I'm creating a script that uses an external program that interacts with a server.
I want to test first that the program is installed before trying to use it.
I looked up the preferred way to tell if a program was installed and found this post:
How can I check if a program exists from a Bash script?
TLDR: It recommends "command -v <prog-name>" over "which <prog-name>" since it is POSIX compatible. The command should return 0 if the program was found, >0 otherwise.
So I used readProcessWithExitCode from System.Process as follows
readProcessWithExitCode "command" ["-v", "<some-program>"] ""
I get the following error when testing in GHCI
Exception: command: readCreateProcessWithExitCode: posix_spawnp: does not exist (No such file or directory)
I tried to use 'which' on 'command'. It tells me it does not exist although I can use it and it works as described in the man pages in my terminal.
What's going on here and how do I see if something is installed using Haskell?
Some system information:
GHC: 9.0.2
resolver: lts-19.11
"I use Arch btw"
I recommend that you simply run the program you want to run, and catch the exception you get if it isn't available. Like this:
catch
(callProcess "lol-this-does-not-exist" []) -- or whatever
(\e -> if isDoesNotExistError e then putStrLn "yikes" else throw e)

How to produce a make build that is verbose only on failure

There are many ways to produce a verbose make command with cmake.
This has been described in many places. (basically cmake; make VERBOSE=1 or set the CMAKE_VERBOSE_MAKEFILE variable).
Verbose here refers to showing the invoked commands and other information on the steps taken by make.
This seems to be an all or nothing setting.
Either you see all the commands or none of the commands,
regardless of the whether the command succeed or not.
A related tool, ctest (for testing) has a very useful options --output-on-failure for which verbosity depends on the particular test being successful;
only showing the screen out for failing tests.
The question is whether cmake has a similar feature regarding giving details only on failure.
That is, for the most part I don't want to see make compilation commands, but when it fails I would like to see what is the exact command that failed with all the options on display.
That is, the question is if there is some setting or command-line option for make or cmake that, in the build step, will print the full issued command (and output) only for commands that failed.
The reason of course is that it gives the opportunity to see the actual compilation flags for the failing step and allows to reproduce the exact command interactively sometimes.
(I use C++, but the question is general I think)
This is not exactly an answer because you only mentioned make, but what you ask is the default behavior of Ninja. It only outputs the command that failed.
Sometimes, when I am too desperate and I cannot understand the error messages I do this:
make -j 10 -k || make VERBOSE=1
So it will compile fast, and if it fails it runs again serially in verbose mode. It is very likely that the first compilation is the one failing.

PVS-Studio: No compilation units were found

I'm using PVS-Studio in docker image based on ubuntu:18.04 for cross-compiling a couple of files with arm-none-eabi-gcc. After doing pvs-studio-analyzer trace -- .test/compile_with_gcc.sh strace_out file is successfully created, it's not empty and contains calls to arm-none-eabi-gcc.
However pvs-studio-analyzer analyze complains that "No compilation units were found". I tried using --compiler arm-none-eabi-gcc key with no success.
Any ideas?
The problem was in my approach to compilation. Instead of using a proper build system, I used a wacky shell script (surely, I thought, using a build system for 3 files is an overkill, shell script won't hurt anybody). And in that script I used grep to redefine one constant in the source - kinda like that: grep -v -i "#define[[:blank:]]\+${define_name}[[:blank:]]" ${project}/src/main/main.c | ~/opt/gcc-arm-none-eabi-8-2018-q4-major/bin/arm-none-eabi-gcc -o main.o -xc
So compiler didn't actually compiled a proper file, it compiled output of grep. So naturally, PVS-Studio wasn't able to analyze it.
TL;DR: Don't use shell scripts as build system.
We have reviewed the stace_out file. It can be handled correctly by the analyzer, if the source files and compilers are located by the absolute path in the stace_out file. We have a suggestion what might help you. You can "wrap" the build command in a call to pvs-studio-analyzer -- trace and pvs-studio-analyzer analyze and place them inside your script (compile_with_gcc.sh). Thus, the script should start with the command:
pvs-studio-analyzer trace --
and end with the command:
pvs-studio-analyzer analyze
This way we will make sure that the build and analysis were started at the same container run. If the proposed method does not help, please describe in more detail, by commands, the process of building the project and running the analyzer. Also tell us whether the container reruns between the build and the formation of strace_out, and the analysis itself.
It would also help us a lot if you ran the pvs-studio-analyzer command with the optional --dump-log flag and provided it to us. An example of a command that can be used to do this:
pvs-studio-analyzer analyze --dump-log ex.log
Also, it seems that it is not possible to quickly solve the problem and it is probably more convenient to continue the conversation via the feedback form on the product website.

Rust std::process with special characters

I've got a very simple rust program but its not doing quite what I'd expect. Running on Windows, using a powershell prompt, I can do the following to display the path:
echo "%PATH%"
and I have a simple Rust program with:
Command::new("echo")
.arg("%PATH%")
.spawn()
.expect("ls command failed to start");
The command will launch and run, but it outputs:
%PATH%
instead of the path contents, like I'd expect. Other commands which don't use special characters seem to work as expected, so I suspect its related to handling them but I don't see a way in Rust to make the command any more primitive than it already is.
I've tried various formatting but it either fails to run the command or does the same.
I also tried using $env:path, but this always fails to run from Rust with a cannot find the path specified error.
Are there any suggestions for handling this? I could write the contents to a file and run the file instead, but running these types of commands from other languages directly works fine so I think it should work from Rust as well.
Thanks!
Update:
Managed to get the expected results from by using:
let out = Command::new("cmd")
.arg("/C")
.arg("echo %PATH%")
.spawn()
.expect("ls command failed to start");
}
I think the question got interpreted a bit differently, as getting the path was just an example of a larger issue I was seeing. Updating with the above solved my larger issue as well.
As the comment by French says: Spawning the process does not include the Powershell-environment, which would expand %PATH% to it's actual content before launching the process.
You need to get the content of PATH via std::env yourself or lookup the Powershell documentation on how to launch a subprocess inside a powershell-session.
As others have mentioned, it's not the special characters, it's the fact that those special characters are interpreted by powershell before the "echo" program runs at all.
Using https://doc.rust-lang.org/cargo/reference/environment-variables.html as a reference for how to look up environment variables, try something like this:
use std::env;
fn main() {
let cur_path = env::var("PATH").unwrap();
println!("Environment is: {}", cur_path);
}
You can try this here: https://play.rust-lang.org/
You can then feed cur_path into your "Command::new" if you wish. The trick is that powershell substitutes that argument BEFORE launching echo, which you may not have known, whereas when you execute the echo program directly, you have to do that substitution yourself.

Bash script - run process & send to background if good, or else

I need to start up a Golang web server and leave it running in the background from a bash script. If the script in question in syntactically correct (as it will be most of the time) this is simply a matter of issuing a
go run /path/to/index.go &
However, I have to allow for the possibility that index.go is somehow erroneous. I should explain that in Golang this for something as "trival" as importing a module that you then fail to use. In this case the go run /path/to/index.go bit will return an error message. In the terminal this would be something along the lines of
index.go:4:10: expected...
What I need to be able to do is to somehow change that command above so I can funnel any error messages into a file for examination at a later stage. I tried variants on go run /path/to/index.go >> errors.txt with the terminating & in different positions but to no avail.
I suspect that there is a bash way to do this by altering the priority of evaluation of the command via some judiciously used braces/brackets etc. However, that is way beyond my bash capabilities. I would be most obliged to anyone who might be able to help.
Update
A few minutes later... After a few more experiments I have found that this works
go run /path/to/index.go &> errors.txt &
Quite apart from the fact that I don't in fact understand why it works there remains the issue that it produces a 0 byte errors.txt file when the command goes to completion without Golang throwing up any error messages. Can someone shed light on what is going on and how it might be improved?
Taken from man bash.
Redirecting Standard Output and Standard Error
This construct allows both the standard output (file descriptor 1) and the standard error output (file descriptor 2) to be redirected to the file whose name is the expansion of word.
There are two formats for redirecting standard output and standard error:
&>word
and
>&word
Of the two forms, the first is preferred. This is semantically equivalent to
>word 2>&1
Appending Standard Output and Standard Error
This construct allows both the standard output (file descriptor 1) and the standard error output (file descriptor 2) to be appended to the file whose name is the expansion of word.
The format for appending standard output and standard error is:
&>>word
This is semantically equivalent to
>>word 2>&1
Narūnas K's answer covers why the &> redirection works.
The reason why the file is created anyway is because the shell creates the file before it even runs the command in question.
You can see this by trying no-such-command > file.out and seeing that even though the shell errors because no-such-command doesn't exist the file gets created (using &> on that test will get the shell's error in the file).
This is why you can't do things like sed 'pattern' file > file to edit a file in place.

Resources