Erlang: Cannot include header - include

I start like this:
[root#Oracle-linux-60 rabbitmq_server-3.5.6]# erl -pa ebin
Erlang/OTP 18 [erts-7.1] [source] [64-bit] [async-threads:10] [hipe] [kernel-poll:false]
Eshell V7.1 (abort with ^G)
1> -include("include/amqp_client.hrl").
** exception error: undefined shell command include/1
Why it doesn't recognize include?

Erlang modules are really forms, but these directives are not 'Erlang' and can't be compiled, therefore this does not work.
If you want to import records you can do it with rr("include/amqp_client.hrl").

You can only enter expressions in the Erlang shell, and -include is not an expression. Similarly you can't define named functions, declare modules, etc. See e.g. http://ulf.wiger.net/weblog/2007/11/20/extending-the-erlang-shell-part-1/

Related

My compiler doesn't parse escape sequences as expected

I am trying to run static analysis on my code using a tool. The Makefile contains:
export TASK=MY_TASK_NAME
my_static_code_tool.exe <arguments> -- gcc <arguments..> -D__TASK_NAME__=\"$(TASK)\" -o missionFile.o missionFile.c
I find that this executes without an issue on RedHat but fails to run on my Cygwin environment. I assign __TASK_NAME__ variable to an unsigned char in a C file such as:
const unsigned char TASK_NAME[] = __TASK_NAME__;
I get the error as:
gcc: no input files
I am very sure my arguments are all correct and I am referring to sources in the correct directory. To me it looks as if the -- stops the parsing of escape sequences in the command on Windows. Can anybody help me with a workaround?
The -- is used by the tool to introduce the compiler and its arguments [and thereby inform the tool that the following is compiler specific]. The GCC had all the required source/files/configuration defined in the Makefile. However it was not processed completely in the Cygwin shell (the command processing stopped with the escaping hence the corresponding gcc error).
The solution I employed to make this work was pre-processor stringification.
C file:
#define STRINGIFY_IT(str) STRING_OF(str)
#define STRING_OF(str) #str
const unsigned char TASK_NAME[] = STRINGIFY_IT(__TASK_NAME__);
Makefile:
export TASK=MY_TASK_NAME
my_static_code_tool.exe <arguments> -- gcc <arguments..> -D__TASK_NAME__=$(TASK) -o missionFile.o missionFile.c
So, if any of you face such problems in the future with 3rd party tools, try not to pass string arguments through the command line to GCC (as they will need to be escaped and might break the command)

The make on FreeBSD doesn't support "ifdef" directives

My FreeBSD is 11.0, and find the make can't process the ifdef directives. For example:
ifdef VERBOSE
Q :=
else
Q := #
endif
The make will complain:
make: "/root/Project/powermon/Makefile" line 13: Need an operator
make: "/root/Project/powermon/Makefile" line 15: Need an operator
make: "/root/Project/powermon/Makefile" line 17: Need an operator
My current solution is using gmake instead. So does any make port on FreeBSD support processing ifdef?
BSD make uses different syntax and has different features than GNU make. The snippet you show should look like the following for BSD make:
.ifdef VERBOSE
Q :=
.else
Q := #
.endif
You have basically three options:
If your software targets specifically BSD, write your Makefile in BSD make syntax. man make(1) has the complete manual for FreeBSD's make.
Write a portable Makefile. This would only use the most basic features of make that every known make tool implements (e.g. don't use any pattern rules etc). This can be tedious and there are other tools helping to manage this by generating the Makefile like cmake or the GNU autotools.
write a GNU make Makefile (might be a good idea to name it GNUmakefile, so it is never interpreted by any other make than GNU make) and rely on the fact that GNU make is available nearly everywhere. For FreeBSD, this would mean installing the appropriate port.
If you go with the third option, you can add a "wrapper" Makefile like e.g. this:
GNUMAKE?= gmake
all:
${GNUMAKE} $#
.DEFAULT:
${GNUMAKE} $#
.PHONY: all
Typing make on BSD will cause the BSD make to read this file and accordingly call gmake. On a GNU system (where make is GNU make), this file will be ignored when there is a GNUmakefile -- GNU make prefers this over just Makefile.
A more portable way to write something like that is:
Q$(VERBOSE) := #

Makefiles and metadata drawn from entire codebase: Accelerating build using diff between old/new

I have a build system with a preprocessor that uses static information from the whole codebase.
[metadata]
|
[input] -(preprocess)-> [source] -(compile)-> [executable]
Important notes:
Both (preprocess) and (compile) can take a considerable amount of time per source file.
[metadata] usually changes everytime you edit any sourcefile in the repository.
So, obviously something needs to be done to cut down on recompiles. So I thought to be clever and did a script that basically works like this:
create [source_temp] using [input] and [metadata]
does [source] not exist yet or is [source_temp] different? --> move [source_temp] to [source]
This works in that recompiles only happen when there is an actual change in [source].
However
In the case when [source] == [source_temp], [source] stays older than [metadata]. So next time I'm running make, even though [metadata] hasn't changed from before, all the (preprocess) commands are repeated since [metadata] is newer.
So... what's the most elegant way to
have GNU Make not run (preprocess) if both [metadata] and [input] hasn't changed since the last build AND
have GNU Make not run (compile) if [source] didn't change (logically) since the last build.
All I can think currently is to screw with the modified dates of files (not even sure if possible) and set modified of [metadata] to the oldest date of all [source]. Is there a better way?
When writing this question I had an idea for an answer. This isn't intirely according to the Makefile spirit of always touching targets, but I think it should work for my usecase:
[source_temp] : [source] [metadata]
< $< (preprocess) > $#
[source] : [source_temp]
copy $< to $# if new or changed
[executable] : [source]
(compile) -c $< -o $#
As you can see the second line doesn't always touch $# but I think I can live with that. The big advantage of this is that it will only execute all the diff commands in the second rule every time, which should be considerably faster than (preprocess).
What's your opinion on this solution?

How does gcc find as, ld and other binutils executables?

Is their location hardcoded into gcc code or does gcc just call as and we must have as location in our PATH variable?
And in the latter case, how could we create two completely separate gcc toolchains? I mean, how can we make gcc-A invoke as-A and gcc-B invoke as-B if as-A and as-B are both called as?
Some of the paths (e.g., to cc1) are compiled in. Others (e.g., as) use normal lookup in $PATH. This can vary depending on the options GCC is configured with.
You can tell fairly easily by running with strace, and grepping for exec|stat.
$ strace -f gcc foo.c -o foo |& grep exec
⋮
[pid 24943] execve("/usr/lib/x86_64-linux-gnu/gcc/x86_64-linux-gnu/4.6.1/cc1", …
That is a call to cc1 by a compiled-in path, as you can see from the
lack of looking for it. Its also not in $PATH.
[pid 24944] execve("/home/anthony/bin/as", ["as", "--64", "-o", "/tmp/ccCIrcGi.o", "/tmp/ccbw3PkL.s"], [/* 51 vars */]) = -1 ENOENT (No such file or directory)
[pid 24944] execve("/usr/local/bin/as", ["as", "--64", "-o", "/tmp/ccCIrcGi.o", "/tmp/ccbw3PkL.s"], [/* 51 vars */]) = -1 ENOENT (No such file or directory)
[pid 24944] execve("/usr/bin/as", ["as", "--64", "-o", "/tmp/ccCIrcGi.o", "/tmp/ccbw3PkL.s"], [/* 51 vars */]) = 0
That is looking for as in $PATH. You can tell because its trying each
location in $PATH in order.
I've omitted a lot of strace output—even with just stat and exec, its
several pages long.
Running gcc -v will show you some of the compiled-in paths (as part of the configure line).
How could we create two completely separate gcc toolchains?
Compile GCC from source twice, detailed instructions at: Multiple glibc libraries on a single host
Everything is hardcoded and highly coupled as far as I can see, I don't think there is any other decent solution.
Query the GCC search path
You can also query the GCC search path with:
gcc -print-search-dirs | grep -E '^programs' | tr ':' '\n'
sample output:
programs
=/usr/lib/gcc/x86_64-linux-gnu/6/
/usr/lib/gcc/x86_64-linux-gnu/6/
/usr/lib/gcc/x86_64-linux-gnu/
/usr/lib/gcc/x86_64-linux-gnu/6/
/usr/lib/gcc/x86_64-linux-gnu/
/usr/lib/gcc/x86_64-linux-gnu/6/../../../../x86_64-linux-gnu/bin/x86_64-linux-gnu/6/
/usr/lib/gcc/x86_64-linux-gnu/6/../../../../x86_64-linux-gnu/bin/x86_64-linux-gnu/
/usr/lib/gcc/x86_64-linux-gnu/6/../../../../x86_64-linux-gnu/bin/
and a specific program with:
gcc -print-prog-name=cc1
sample output:
/usr/lib/gcc/x86_64-linux-gnu/6/cc1
GCC spec files
It is wort mentioning that what actually determines the final cpp, ld, as are the "spec" files in the GCC source code, see also: What are GCC's passes and invoked programs?
There's an ad-hoc option for that: -B*prefix*, quoting gcc docs:
For each subprogram to be run, the compiler driver first tries the -B prefix, if any. If
that name is not found, or if -B was not specified, the driver tries two standard prefixes,
which are /usr/lib/gcc/ and /usr/local/lib/gcc/. [...]

Problem starting program (vcom) with multiple arguments in TCL

I'm trying to start a program (vcom) from a TCL script with extra options:
set compilationArgs "-quiet -93"
vcom $compilationArgs -work work polar2rect/sc_corproc.vhd
But when I run this, I get following error message:
# Model Technology ModelSim ALTERA vcom 6.5e Compiler 2010.02 Feb 27 2010
# ** Error: (vcom-1902) Option "-quiet -93" is either unknown, requires an argument, or was given with a bad argument.
# Use the -help option for complete vcom usage.
# /opt/altera/10.0/modelsim_ase/linuxaloem/vcom failed.
TCL seems to pass the two extra options (-quiet) and (-93) as one option to vcom. If I use only one of these two options it works. And if I run (vcom -93 -quiet -work work polar2rect/sc_corproc.vhd) it also works.
How can I fix this?
Thanks,
Hendrik.
The “problem” is that Tcl's being careful about managing spaces. This is very useful if you've got arguments with spaces in (such as many full filenames on Windows machines) but can sometimes be frustrating if you wanted the list to be broken up automatically. The fix is to indicate to Tcl that this is something that you want split into multiple words.
The best answer requires at least Tcl 8.5 (find out what version you've got with info tclversion, info patchlevel, or package require Tcl).
vcom {*}$compilationArgs -work work polar2rect/sc_corproc.vhd
If you're built against an older version of Tcl, you'll need this instead:
eval vcom $compilationArgs -work work polar2rect/sc_corproc.vhd
(Or this, to be officiously correct, but hardly anyone bothers for obvious reasons)
eval [list vcom] $compilationArgs [list -work work polar2rect/sc_corproc.vhd]
The version at the top with the expansion syntax ({*}) is best if supported. You can determine if it is easily enough; if it isn't, it's a syntax error.

Resources