How do I make a Makefile target depend on a file that only possibly exists? - language-agnostic

I have a set of files of the form [name].c, some of which #include an associated [name].h file. I want a makefile target that re-builds [name].o if [name].c or [name].h are modified. I tried:
$(OBJDIR)/%.o : $(SRCDIR)/%.c $(SRCDIR)/%.h
#Implementation of target omitted
However, for the .c files that don't have associated .h files, make complains on the above rule. I tried:
$(OBJDIR)/%.o : $(SRCDIR)/%.c $(wildcard $(SRCDIR)/%.h)
#Implementation of target omitted
This builds, but modifying the .h files does not trigger a rebuild. Is there some reason I can't use % in this way?
Note: I'm trying to avoid a solution that uses makedeps.pl or makefile generation (because I am not actually working with .c or .h files).

Your attempt won't work because variables and functions that appear as part of target or prerequisite lists are expanded immediately, when the makefile is read in. At that point, obviously, there's no way to know what % might expand to later, when make is trying to figure out how to build targets, so it's actually expanding the literal string <srcdir>/%.h of which presumably there is none.
One answer is to move the prerequisites to a separate rule:
$(OBJDIR)/foo.o : $(wildcard $(SRCDIR)/foo.h)
$(OBJDIR)/bar.o : $(wildcard $(SRCDIR)/bar.h)
$(OBJDIR)/baz.o : $(wildcard $(SRCDIR)/baz.h)
If you don't want to have to write this out, you can use eval to do it for you: suppose you have a variable listing the object files:
OBJECTS = foo.o bar.o baz.o
$(foreach O,$(OBJECTS),$(eval $(OBJDIR)/$O : $(wildcard $(SRCDIR)/$(O:.o=.h))))
(that might not be exactly right).
Alternatively, you can enable .SECONDEXPANSION and write:
.SECONDEXPANSION:
$(OBJDIR)/%.o : $(SRCDIR)/%.c $$(wildcard $(SRCDIR)/%.h)
#Implementation of target omitted
(note the extra $ escaping the wildcard function).

Related

How to include files in icarus verilog?

I know the basic `include "filename.v" command. But, I am trying to include a module which is in another folder. Now, that module further includes other modules present in the same folder. But, when I try to run the module on the most top-level, I am getting an error.
C:\Users\Dell\Desktop\MIPS>iverilog mips.v
./IF/stage_if.v:2: Include file instruction_memory_if.v not found
No top level modules, and no -s option.
Here, I am trying to make a MIPS processor, which is contained in the file "mips.v". The first statement of this file is "`include "IF/stage_if.v". And, in the IF folder, there are numerous files present which I have included in stage_if.v, one of which is "instruction_memory_if.v". Below is the directory level diagram.
-IF
instruction_memory_if.v
stage_if.v
+ID
+EX
+MEM
+WB
mips.v
You need to tell iverilog where to look using the -I flag.
In top.v:
`include "foo.v"
program top;
initial begin
foo();
end
endprogram
In foo/foo.v:
task foo;
$display("This was printed in the foo module");
endtask
Which can be run using the commands:
iverilog -g2012 top.v -I foo/
vvp a.out
>>> This was printed in the foo module

Converting Tcl to C++

I am trying to convert some tcl script into a C++ program. I don't have much experience with tcl and am hoping someone could explain what some of the following things are actually doing in the tcl script:
1) set rtn [true_test_sfm $run_dir]
2) cd [glob $run_dir]
3) set pwd [pwd]
Is the first one just checking if true_test_sfm directory exists in run_dir?
Also, I am programming on a windows machine. Would the system function be the equivalent to exec statements in tcl? And if so how would I print the result of the system function call to stdout?
In Tcl, square brackets indicate "evaluate the code between the square brackets". The result of that evaluation is substituted for the entire square-bracketed expression. So, the first line invokes the function true_test_sfm with a single argument $run_dir; the result of that function call is then assigned to the variable rtn. Unfortunately, true_test_sfm is not a built-in Tcl function, which means it's user-defined, which means there's no way we can tell you what the effect of that function call will be based on the information you've provided here.
glob is a built-in Tcl function which takes a file pattern as an argument and then lists files that match that pattern. For example, if a directory contains files "foo", "bar" and "baz", glob b* would return a list of two files, "bar" and "baz". Therefore the second line is looking for any files that match the pattern given by $run_dir, then using the cd command (another Tcl built-in) to change to the directory found by glob. Probably $run_dir is not actually a file pattern, but an explicit file name (ie, no globbing characters like * or ? in the string), otherwise this code may break unexpectedly. On Windows, some combination of FindFirstFile/FindNextFile in C++ could be used as a substitute for glob in Tcl, and SetCurrentDirectory could substitute for cd.
pwd is another built-in Tcl function which returns the process current working directory as an absolute path. So the last line is querying the current working directory and saving the result in a variable named pwd. Here you could use GetCurrentDirectory as a substitute for pwd.

Using mxmlc to compile as files with more than one src paths

I am using mxmlc.exe to compile my Flash project but I have two separated source files.
I noticed that I can specify more than one -compiler.library-path but it seems not OK to specify more than one -compiler.source-path parameters.
For some reasons I have to keep the src files in different folders. Is there any way I can still compile?
Thanks!
The desired command-line parameters:
mxmlc.exe src/Editor.as
-output=Editor.swf
-compiler.source-path=src1 -compiler.source-path=../src2
-compiler.library-path=libs -compiler.library-path=../libs
The += operator will append the second path to compiler.library-path, whereas the = operator will replace the value with a new one.
try this instead:
mxmlc.exe src/Editor.as
-output=Editor.swf
-compiler.source-path=src1 -compiler.source-path=../src2
-compiler.library-path+=libs -compiler.library-path=../libs
You might have to play a bit with the spacing before and after the += to get it working exactly right.

cscope and ctag cannot find a function definition which is located in class declaration

I use vim + ctag + cscope when I browse C++ source code.
When I want to look up a definition of any function cscope and/or ctag produce a list of cadidates which seem to be the one.
But when I try this for a function which is defined in a class declaration in a header file, none of those two produce the list of cadidates.
When ctag and/or cscope fail like this I now know that the function definition should be in a header file. So I open the header file and find the function definition in it.
But I wonder if this is inevitable behavior of ctag and cscope.
Aren't there any way to make them(ctag and cscope) clever for this kind of cases so that I can find the definition of every function even though they are defined in a header file?
Thank you very much.
Journeyer J. Joh
I generated tag file like the one below.
ctags --langmap=C++:.inc --c++-kinds=+p --fields=+iaS --extra=+fq --sort=foldcase -R .
But it has to be corrected the way below.
ctags --langmap=C++:+.inc --c++-kinds=+p --fields=+iaS --extra=+fq --sort=foldcase -R .
from
--langmap=C++:.inc
to
--langmap=C++:+.inc
man ctags has instruction for this:
[...] to specify that only files with extensions of .c and .x are to be treated as C language files, use "--langmap=c:.c.x"; to also add files with extensions of .j as Java language files, specify "--langmap=c:.c.x,java:+.j".

How to source a script file by passing arguments?

Say I have a tcl script and I want to pass some arguments to the second script file which is being sourced in the first tcl:
#first tcl file
source second.tcl
I want to control the flow of second.tcl from first.tcl and I read that tcl source does not accept arguments. I wonder how I can do then.
source does not accept any additional arguments. But you can use (global) variables to pass arguments, e.g.:
# first tcl file
set ::some_variable some_value
source second.tcl
The second TCL file can reference the variable, e.g.:
# second tcl file
puts $::some_variable
Remark:
Sourcing a file means that the content of the sourced script is executed in the current context. That means that the sourced script has access to all variables existing in that context. The above code is the same as:
# one joint tcl file
set ::some_variable some_value
puts $::some_variable
Regarding the "::" thing -- see the explanation here (sorry, I don't have enough rep. to leave comments yet).
I should also add that the original question discusses a problem which appears to be quite odd: it seems that it could be better to provide a specific procedure in your second source file that would set up a state pertaining to what is defined by that script.
Something like:
source file2.tcl
setup_state $foo $bar $baz
Making [source] behave differently based on some global variables looks too obscure to me. Of course you might have legitimate reasons to do this, but anyway...