How to avoid output synchronization problems in parallel builds? - shake-build-system

When using parallel builds in shake, i get malformed output like this:
[»] Compiling src/Game/Game.cpp
[»] Compiling [»] Compiling [»] Compiling src/Graphics/Image/Png/PngLoader.cpp
src/Main.cpp
src/System/HeartBeat.cpp
[»] Compiling src/Window/Window.cpp
[»] Compiling src/Window/GlfwContext.cpp
I suppose that it is some kind of synchronization problem with my printing.
I should note that i am using the following as an output command:
shakeOutput = const $ BS.putStr . BS.pack
And the status message printing section my rules looks like this:
liftIO $ setSGR [SetColor Foreground Vivid Green]
putNormal "[\175] Compiling "
liftIO $ setSGR [SetColor Foreground Vivid Yellow]
putNormal $ c ++ "\n"
liftIO $ setSGR [Reset]
Is there a way to avoid that kind of printing problems with my output built in in shake? If not what kind of haskell syncronization method would be appropriate to use, knowing that the printing code is inside a shake rule?

The reason shakeOutput defaults to const $ BS.putStr . BS.pack is because the BS.putStr takes the Haskell console lock, and thus ensures output isn't interleaved. I don't believe this is a contractual guarantee of BS.putStr, but if it ever stops being so, I will add a lock around shakeOutput by default. There are two approaches to fix the problem:
Add a lock
One approach is to add a lock, ideally a renterant Mutex (not something I've seen in Haskell already, but can be synthesised relatively easily on top of MVar and myThreadId). Then you make shakeOutput take the lock, and in your snippets which call shakeOutput multiple times you also take the lock around the entire block. The Mutex probably wants to be stored in a top-level unsafePerformIO CAF.
Use a single shakeOutput call
Since shakeOutput is already atomic you can just reuse that property by rewriting your code as:
putNormal $
setSGRCode [SetColor Foreground Vivid Green] ++
"[\175] Compiling " ++
setSGRCode [SetColor Foreground Vivid Yellow] ++
c ++ "\n" ++
setSGRCode [Reset]
I'd encourage the second approach, since it's much simpler, and also makes sure that if the verbosity is turned to quiet the codes don't still get printed.

My approach was to use resources:
con <- newResource "Console" 1
let withConsole = withResource con 1 . liftIO

Related

Equivalent of bash's -x debug flag for C programs?

I always use the -x (or debug flag) when it come to bash script, or shell scripts in general.
Now i'm curious to know, is there an equivalent, either using a specific compiler options, (i use gcc, but i don't mind any other compilers) or by using a specific code in my project?
Basically i just wanted a way to emulate what bash does (using the debug flag) which show which command/function was launched first, in order, and also show the output of said function, with additional errors message etc.But for C.
I'm aware of most debug option out there, especially considering the compiler, but i really wish i could do this in my C projects too.(especially the part where it show what is executed in order, like bash does with -x)
NB: There isn't any goal in this specific question beside the question itself, as i'm just curious if this exist, and thus don't have any need for it beside the actual knowledge acquired from said answered question.
Yes, you can mimic this behaviour with a debugger.
With GDB for instance you can write "Init Files" and "Command Files" in which you can write a simple loop:
break main
run
while 1
next
end
If you put a file named .gdbinit in the directory where you start gdb, this file will be executed or gdb will lead you on the way to configure it in order that it will be executed.
The other option is to pipe this file into your gdb-call:
gdb a.out < debug_me_like-x
Where the "debug_me_like-x" file is the one mentioned above.
As a reference for the "Command Files" have a look here.

May I set TERM environment variable safely?

I'm writing a program that uses termcaps and I need to know which kind of terminal I am using.
I am aware I can get TERM variable via getenv("TERM"), but I can launch my program with "$ env -i ./myprog" and TERM will not be set.
So how can I determine which terminal type must I use?
May I safely set TERM variable to xterm/xterm-256color in my application?
Will it cause non-portability issues?
Is there a method to do such (get termtype) safely?
I've red many manuals (getty - getttab - tty - ttys) and posts but I can't spot any solution.
I'm also worried because if I launch a shell (like zsh or tcsh) I have issues with some keys.
For example launching zsh like so:
$env -i zsh
will cause troubles with arrows and any keys implying termcaps (even Ctr-d).
Instead bash and tcsh will behave normally on many keys but not all.
If you're actually using termcap (and not some minimal implementation such as busybox), you're likely using a system that provides tset, which can offer the user a default choice for TERM that can be modified.
Something like this:
eval `tset -s vt100`
in the shell initialization would work.
Actually tset isn't limited to termcap-systems, but that's where it started.
Further reading:
tset, reset -- terminal initialization (FreeBSD)
tset, reset - terminal initialization (ncurses)
tset, reset - terminal initialization (NetBSD)
It is (somewhat) safe to set TERM=vt100 as default (Ctx's suggestion), as most terminal emulators are set to emulate that anyway. I'd recommend you to print a warning in this case, though.

How to override Shake configuration on the command-line

I maintain small configuration files per project read via usingConfigFile. I'd like to be able to override any of those settings on the command line. It seems using shakeArgsWith (rather than shakeArgs) is the first step on the way but I don't see an obvious way to wire that through to the values produced by getConfig. Is there a standard approach for doing this?
There isn't a standard approach, but I know several larger build systems have invented something. A combination of shakeArgsWith, readConfigFile and usingConfig should do it. Something like (untested):
main = shakeArgsWith shakeOptions [] $ \_ args -> return $ Just $ do
file <- readConfigFile "myfile.cfg"
usingConfig $ Map.union (argsToSettings args) file
myNormalRules
Where argsToSettings is some function that parses your arguments and turns them into settings - e.g. breaking on the first = symbol or similar.

Syntax error near unexpected token '('

As a beginner, I am trying to write a simple c program to learn and execute the "write" function.
I am trying to execute a simple c program simple_write.c
#include <unistd.h>
#include <stdlib.h>
int main()
{
if ((write(1, “Here is some data\n”, 18)) != 18)
write(2, “A write error has occurred on file descriptor 1\n”,46);
exit(0);
}
I also execute chmod +x simple_write.c
But when i execute ./simple_write.c, it gives me syntax error near unexpected token '('
Couldn't figure out why this happens ??
P.S: The expected output is:-
$ ./simple_write
Here is some data
$
You did
$ chmod +x simple_write.c
$ ./simple_write.c
when you should have done
$ cc simple_write.c -o simple_write
$ chmod +x simple_write # On second thought, you probably don’t need this.
$ ./simple_write
In words: compile the program to create an executable simple_write
(without .c) file, and then run that. 
What you did was attempt to execute your C source code file
as a shell script.
Notes:
The simple_write file will be a binary file. 
Do not look at it with tools meant for text files
(e.g., cat, less, or text editors such as gedit).
cc is the historical name for the C compiler. 
If you get cc: not found (or something equivalent),
try the command again with gcc (GNU C compiler). 
If that doesn’t work,
If you’re on a shared system (e.g., school or library),
ask a system administrator how to compile a C program.
If you’re on your personal computer (i.e., you’re the administrator),
you will need to install the compiler yourself (or get a friend to do it). 
There’s lots of guidance written about this; just search for it.
When you get to writing more complicated programs,
you are going to want to use
make simple_write
which has the advantages of
being able to orchestrate a multi-step build,
which is typical for complex programs, and
it knows the standard ways of compiling programs on that system
(for example, it will probably “know” whether to use cc or gcc).
And, in fact, you should be able to use the above command now. 
This may (or may not) simplify your life.
P.S. Now that this question is on Stack Overflow,
I’m allowed to talk about the programming aspect of it. 
It looks to me like it should compile, but
The first write line has more parentheses than it needs.
if (write(1, "Here is some data\n", 18) != 18)
should work.
In the second write line,
I count the string as being 48 characters long, not 46.
By the way, do you know how to make the first write fail,
so the second one will execute?  Try
./simple_write >&-
You cannot execute C source code in Linux (or other systems) directly.
C is a language that requires compilation to binary format.
You need to install C compiler (the actual procedure differs depending on your system), compile your program and only then you can execute it.
Currently it was interpreted by shell. The first two lines starting with # were ignored as comments. The third line caused a syntax error.
Ok,
I got what i was doing wrong.
These are the steps that I took to get my problem corrected:-
$ gedit simple_write.c
Write the code into this file and save it (with .c extension).
$ make simple_write
$ ./simple_write
And I got the desired output.
Thanks!!

Is there something like IDLE (python) for C? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Is there an interpreter for C?
I want to practice C a bit and I would like to have something that allows to write and test C code quickly. I want to have an interpreter with UI where I can write my code and execute it.
Are there any good solutions for that?
The closest solution to what you are looking for seems to be the C shell (CSH) or C Scripting Language (CSL).
Alternatively, have an editor open where you will write your C sample, then have console window where you will execute your favourite C compiler. The idea is to have simple workflow like this:
$ gvim test.c
$ gcc test.c
$ ./a.out
Don't forget, C is not a scripting language.
However, you may find JIT compiler for C, C++, and the likes discussion helpful.
Though "interpreters" per se don't exist (or not practically), I'd advise on using a modern IDE. Eclipse + CDT allows you to have "on the fly compilation", just like in java. Your project is ready to run whenever you are, with reduced latency due to compilation (if you have a decent computer).
For other answers, I advise on NOT using directly gcc test.c. Use a makefile or use at least gcc -Wall -g -o myapp test.c top have additional information during compilation (useful as C has many more pitfalls than python). Please note as well that testis astandard program and that . might not be in your PATH : myapp is a better name than test ;-)
There is Cling. Never used it, so I can't really tell you more, but it looks like what you are looking for.
You might also find other lead in this question: Is there an interpreter for C?
you can take a look at : http://codepad.org/
or the easy way is to create a sh script like :
vim $1 ; gcc $1 ; ./a.out
You can't interpret C++ code as far as I know...
What you could do (and what I do when I quickly need to write some simple things ) is set up a simple make file and open a new file with some simple text editor like Kate that has a console plugin. Then you can write some code and type "make" to see the result of your code in the konsole / whichever shell you are using

Resources