scons help for alternate build tools - scons

I'm using a compiler for TI DSPs, so the default CC and LINK and AS tools make no sense. Below is an SConstruct file that works for me, I'm wondering if anyone has suggestions to make it better. Some problems:
I'd like to somehow tell it that my .obj files should go in a different directory than the source .c files. (it needs to know where, in order to figure out the SOURCES for the link step, and the dependencies for compile/linking) It would be nice to tie this in with the "-fr" and "-fs" arguments to the compiler, but I don't mind doing that manually.
There are some stock C files in the SConstruct file below, all start with a prefix of DSP2804x_. Right now scons can't figure out the dependencies for these, because I guess it's expecting the .obj files to live in the same directory, whereas my use of "-fr" and "-fs" for the compiler means those .obj files end up in the same directory as the SConstruct file. Is there a better way to do this? I'm guessing I should probably have a build step that copies these reference files into a local directory: if I change them, I want the changes to propagate to all projects that use them.
sigh....
env = Environment(
CC = 'C:/appl/ti/ccs/3.3/C2000/cgtools/bin/cl2000',
CCCOM = '$CC $CFLAGS $CCFLAGS $SOURCES',
CCFLAGS = Split('-g -q -pdr -d"_DEBUG" -d"LARGE_MODEL" -ml -mt -v28'),
LINKCOM = '$LINK $LINKFLAGS ${SOURCES.file} -o ${TARGET.base}.out',
LINK = 'C:/appl/ti/ccs/3.3/C2000/cgtools/bin/cl2000',
LINKFLAGS = Split('-z -q -c -ecode_start -stack0x200 -w -x'),
ASCOM = '$CC $CFLAGS $CCFLAGS $SOURCES',
#Bizarre but true. assembly is just like compiling C.
);
includes = {'CCFLAGS' : [
'-i../common/headers/include',
'-i../common/include',
'-fr.',
'-fs.'
]};
env.MergeFlags(includes);
links = {'LINKFLAGS' : [
'-m./Debug/Example_2804xGpioToggle.map',
'-i../common/headers/include',
'-iC:/appl/ti/ccs/3.3/C2000/xdais/lib',
'-iC:/appl/ti/ccs/3.3/C2000/cgtools/lib',
'-lrts2800_ml.lib',
'../common/cmd/28044_RAM_lnk.cmd',
'../common/headers/cmd/DSP2804x_Headers_nonBIOS.cmd'
]};
env.MergeFlags(links);
print "CCCOM is:", env['CCCOM'], "\n", env['LINKCOM'], '\n', env['ASCOM'];
env.Program('blink_gpio', [
'Example_2804xGpioToggle.c',
'../common/headers/source/DSP2804x_GlobalVariableDefs.c',
'../common/source/DSP2804x_CodeStartBranch.asm',
'../common/source/DSP2804x_DefaultIsr.c',
'../common/source/DSP2804x_PieCtrl.c',
'../common/source/DSP2804x_PieVect.c',
'../common/source/DSP2804x_SysCtrl.c'
]);

I solved both problems by doing a hierarchical build and using -fr=${TARGET.dir} in my compiler flags.

Related

How is the -fprofile-prefix-path option supposed to work?

When compiling code for coverage instrumentation (to use with lcov later on), we're compiling from a base directory tree (let's call it A), and we want the .gcda files to be produced at a different place (because the target directory tree is different - let's call it B).
So, the compilation command looked like this:
gcc -O0 -g --coverage -fprofile-dir=B -c -fPIC -Wall -o A/otherpath/to/mySourceFile.o A/path/to/mySourceFile.c
When checking the contents of mySourceFile.o (with the strings command), I saw that the mySourceFile.gcda file was set to be generated in B/A/otherpath/to/mySourceFile.gcda
Which is the mangling of the path given through the -fprofile-dir option with the exact absolute path of the object file created - just as written in the documentation. So far, no problem - except that what I want would be the mySourceFile.gcda file to be generated from the B directory, WITHOUT the A part.
So, the documentation also mentions the -fprofile-prefix-path option, which is supposed to allow you to remove part of the path, so that the mangling doesn't add the old path to the new.
I tried using it in the following way:
gcc -O0 -g --coverage -fprofile-dir=B -fprofile-prefix-path=A -c -fPIC -Wall -o A/otherpath/to/mySourceFile.o A/path/to/mySourceFile.c
However, after checking through strings, once again, in the generated object file, the path was still B/A/otherpath/to/mySourceFile.gcda, whereas I expected it to be B/otherpath/to/mySourceFile.gcda (that is, I expected the A part to have been stripped by the -fprofile-prefix-path option.)
Obviously, it didn't work. Any insight why ?
( Compiler used is GCC 11.2.1, which is a version recent enough to know about the option. )
Ok, after some tinkering, I got results. Maybe not exactly what I was expecting, but close enough.
Let me start by saying that the A and B "directories" I mentioned in my question were absolute paths. And it didn't work well.
However, while keeping the absolute B (target) path, I tried not using the full A (source) path while compiling. More precisely, I didn't use it to specify the OUTPUT file name, for the object. Instead, I went to the base directory (the A path), and then, ran the command by specifying the output file path relative to the current (A) directory
Which would give the following command:
(From directory A)
gcc -O0 -g --coverage -fprofile-dir=B -fprofile-prefix-path=A -c -fPIC -Wall -o otherpath/to/mySourceFile.o path/to/mySourceFile.c
This time, the source command did show an interesting result, for the mySourceFile.gcda file:
B#otherpath#to#mySourceFile.gcda
As you can see, it's not exactly what I wanted (there are # instead of /), but mentions to A disappeared, and overall, I'm confident it should work as intended. Not utterly sure yet (I still have to test it on the target platform, which will need tinkering with the way the makefiles currently work), but confident nonetheless.
Also, if I didn't use the -fprofile-prefix-path in the command, then the string would mention the A path, like this (with the '/' inside the A path being replaced with '#' characters, obviously):
B#A#otherpath#to#mySourceFile.gcda
So, the option works, but only when using relative paths, not when using absolute ones, for the object file. Hope that helps people.
PS: I checked by changing the path to the source (.c) file. Whether specified using absolute, or relative, paths, it didn't change the outcome. What matters is specifying the path to the object file in a relative manner.

Is there a way to define custom implicit GNU Make rules?

I'm often creating png files out of dot (graphviz format) files. The command to do so is the following:
$ dot my_graph.dot -o my_graph.png -Tpng
However, I would like to be able to have a shorter command format like $ make my_graph.dot to automatically generate my png file.
For the moment, I'm using a Makefile in which I've defined the following rule, but the recipe is only available in the directory containing the Makefile
%.eps: %.dot
dot $< -o $# -Teps
Is it possible to define custom implicit GNU Make recipes ? Which would allow the above recipe to be available system-wide
If not, what solution do you use to solve those kind of problem ?
Setup:
Fedora Linux with ZSH/Bash
You could define shell functions in your shell's startup files, e.g.
dotpng()
{
echo dot ${1%.dot}.dot -o ${1%.dot}.png -Tpng;
}
This function can be called like
dotpng my_graph.dot
or
dotpng my_graph
The code ${1%.dot}.dot strips .dot from the file name if present and appends it (again) to allow both my_graph.dot and my_graph as function argument.
Is it possible to define custom implicit GNU Make recipes ?
Not without modifying the source code of GNU Make.
If not, what solution do you use to solve those kind of problem ?
I wouldn't be a fan o modyfying the system globally, but you could do:
Create a file /usr/local/lib/make/myimplicitrules.make with the content
%.eps: %.dot
dot $< -o $# -Teps
Use include /usr/local/lib/make/myimplicitrules.make in your Makefile.
I would rather use a git submodule or similar to share common configuration between projects, rather than depending on global configuration. Depending on global environment will make your program hard to test and non-portable.
I would rather go with a shell function, something along:
mymake() {
make -f <(cat <<'EOF'
%.eps: %.dot
dot $< -o $# -Teps
EOF
) "$#"
}
mymake my_graph.dot
GNU Make lets you specify extra makefiles to read using the MAKEFILES
environment variable. Quoting from info '(make)MAKEFILES Variable':
the default goal is never taken from one of these makefiles (or any
makefile included by them) and it is not an error if the files listed
in 'MAKEFILES' are not found
if you are running 'make' without a specific makefile, a makefile
in 'MAKEFILES' can do useful things to help the built-in implicit
rules work better
As an example, with no makefile in the current directory and the
following .mk files in make's include path (e.g. via
MAKEFLAGS=--include-dir="$HOME"/.local/lib/make/) you can create
subdir gen/ and convert my_graph.dot or dot/my_graph.dot by
running:
MAKEFILES=dot.mk make gen/my_graph.png
To further save some typing it's tempting to add MAKEFILES=dot.mk
to a session environment but defining MAKEFILES in startup files
can make things completely nontransparent. For that reason I prefer
seeing MAKEFILES=… on the command line.
File: dot.mk
include common.mk
genDir ?= gen/
dotDir ?= dot/
dotFlags ?= $(if $(DEBUG),-v)
Tvariant ?= :cairo:cairo
vpath %.dot $(dotDir)
$(genDir)%.png $(genDir)%.svg $(genDir)%.eps : %.dot | $(genDir).
dot $(dotFlags) $< -o $# -T'$(patsubst .%,%,$(suffix $#))$(Tvariant)'
The included common.mk is where you'd store general definitions to
manage directory creation, diagnostics etc., e.g.
.PRECIOUS: %/. ## preempt 'unlink: ...: Is a directory'
%/. : ; $(if $(wildcard $#),,mkdir -p -- $(#D))
References:
?= = := … - info '(make)Reading Makefiles'
vpath - info '(make)Selective Search'
order-only prerequisites (e.g. | $(genDir).) - info '(make)Prerequisite Types'
.PRECIOUS - info '(make)Chained Rules'

How to creat only object file without executable?

I am trying to create an object file through a make file which will be called in another script.
The following is my make file for creating an object file.
SOURCE_CK = ../SOURCES_COUNTERFLOW/
SOURCES_f77 = $(SOURCE_CK)density.f
#TARGET =
OBJECTS = $(SOURCES_f77:.f=.o)
COMPILE = f77
.f.o :
$(COMPILE) -o $*.o -c $*.f
#$(TARGET) : $(OBJECTS)
# $(COMPILE) $(OBJECTS) -o $#
#del :
# /bin/rm $(OBJECTS)
When I run the above script, the following error gets generated.
make: *** No targets. Stop.
Now I know I have to make some modification with TARGET but not sure where to start or how to modify the target.
Again, my goal is to run the script and generate density.o file.
Any help would be appreciated.
GNU Make has built-in rules for making fortran object files from sources, and fortran programs from object files, see https://www.gnu.org/software/make/manual/html_node/Catalogue-of-Rules.html
Your makefile can therefore be condensed into just the following:
$(TARGET): $(OBJECTS)
Should you want to generate just the object, you can even do that without a makefile:
# make density.o from a sourcefile
make density.o
Note the built-in rules put the object files next to the source files (unless using VPATH etc etc, more about that in the manual), so you'd call it like
make ../SOURCES_COUNTERFLOW/density.o

How to exclude files without an extension in Sublime Text 3?

I know there is an easy way to do it for known extensions, adding it in excluded patterns in preferences like "*.jpg", but how can I do it for the binary files without any extension at all?
In example, my c compiled files are named with just "name", not "name.o" etc, so is there any trick to exclude them?
To exclude a file with no extension then you must manually add the exact filename for each file that you want excluded.
Using your example, to exclude a file which is called name then add "name" to your file_exclude_patterns list like this:
"file_exclude_patterns": ["*.pyc", "*.pyo", "*.exe", ..., "name"],
Since you mention C compiled files then to avoid having to do this regularly with all your compiled executable files you can do one of several things or some combination or variation of them.
1) Consistently use the same executable file name, for example run, regardless of what you are compiling.
gcc example.c -o run
"file_exclude_patterns": ["*.pyc", "*.pyo", "*.exe", ..., "run"],
2) Choose a consistent prefix for the executable file names, for example run_.
gcc example.c -o run_example
gcc program.c -o run_program
"file_exclude_patterns": ["*.pyc", "*.pyo", "*.exe", ..., "run_*"],
3) Choose a file extension for your executables and use that consistently.
gcc example.c -o example.out
"file_exclude_patterns": ["*.pyc", "*.pyo", "*.exe", ..., "*.out"],
Sorry to update an old question. As of today, we could instead specify "file_include_patterns": ["*.*"] in a project preference to exclude files without an extension from the sidebar.
The "file_include_patterns" consists of an array of glob strings, referred to by ST as file patterns. However, the file pattern of ST only supports two matching operators, * and ?. According to the document, File patterns specified under "file_include_patterns" are
Patterns of files to include from the folder. Anything not matching these patterns will be excluded. This is checked before "file_exclude_patterns".
One could further set the "index_include_patterns": ["*.*"] to prevent ST from indexing symbols from files without an extension. Differences between "file_include_patterns" and "index_exclude_patterns" can be found in #OdatNurd's answer.
An example project configuration file my-project.sublime-project that prevents ST from showing files without an extension in the side bar or indexing symbols from them may look like
{
"folders":
[
{
"file_include_patterns": ["*.*"],
"index_include_patterns": ["*.*"],
"path": "/path/to/your/my-project-folder"
}
]
}
where "/path/to/your/my-project-folder" needs to be set accordingly.
This setting prevents ST from showing or index files without an extension under "/path/to/your/my-project-folder" or its sub-folders.

g++ searches /lib/../lib/, then /lib/

According to g++ -print-search-dirs my C++ compiler is searching for libraries in many directories, including ...
/lib/../lib/:
/usr/lib/../lib/:
/lib/:
/usr/lib/
Naively, /lib/../lib/ would appear to be the same directory as /lib/ — lib's parent will have a child named lib, "that man's father's son is my father's son's son" and all that. The same holds for /usr/lib/../lib/ and /usr/lib/
Is there some reason, perhaps having to do with symbolic links, that g++ ought to be configured to search both /lib/../lib/ and /lib/?
If this is unnecessary redundancy, how would one go about fixing it?
If it matters, this was observed on an unmodified install of Ubuntu 9.04.
Edit: More information.
The results are from executing g++ -print-search-dirs with no other switches, from a bash shell.
Neither LIBRARY_PATH nor LPATH are output from printenv, and both echo $LPATH and echo LIBRARY_PATH return blank lines.
An attempt at an answer (which I gathered from a few minutes of looking at the gcc.c driver source and the Makefile environment).
These paths are constructed in runtime from:
GCC exec prefix (see GCC documentation on GCC_EXEC_PREFIX)
The $LIBRARY_PATH environment variable
The $LPATH environment variable (which is treated like $LIBRARY_PATH)
Any values passed to -B command-line switch
Standard executable prefixes (as specified during compilation time)
Tooldir prefix
The last one (tooldir prefix) is usually defined to be a relative path:
From gcc's Makefile.in
# Directory in which the compiler finds libraries etc.
libsubdir = $(libdir)/gcc/$(target_noncanonical)/$(version)
# Directory in which the compiler finds executables
libexecsubdir = $(libexecdir)/gcc/$(target_noncanonical)/$(version)
# Used to produce a relative $(gcc_tooldir) in gcc.o
unlibsubdir = ../../..
....
# These go as compilation flags, so they define the tooldir base prefix
# as ../../../../, and the one of the library search prefixes as ../../../
# These get PREFIX appended, and then machine for which gcc is built
# i.e i484-linux-gnu, to get something like:
# /usr/lib/gcc/i486-linux-gnu/4.2.3/../../../../i486-linux-gnu/lib/../lib/
DRIVER_DEFINES = \
-DSTANDARD_STARTFILE_PREFIX=\"$(unlibsubdir)/\" \
-DTOOLDIR_BASE_PREFIX=\"$(unlibsubdir)/../\" \
However, these are for compiler-version specific paths. Your examples are likely affected by the environment variables that I've listed above (LIBRARY_PATH, LPATH)
Well, theoretically, if /lib was a symlink to /drive2/foo, then /lib/../lib would point to /drive2/lib if I'm not mistaken. Theoretically...
Edit: I just tested and it's not the case - it comes back to /lib. Hrm :(

Resources