![](/i/fill.gif) |
![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
I've got a couple of Unix questions...
#1: Consider the following:
~$ /usr/bin/time --format="%C\n%E wall time, %P CPU, %M KB maximum"
./Prog1
./Prog1
0:15.27 wall time, 89% CPU, 1608592 KB maximum
The program *actually* used about 400MB of RAM. So WTF is %M actually
measuring? Because it sure as hell isn't "maximum resident set size of
the process during its lifetime, measured in Kilobytes".
(Also, why do %D, %K and %X all return 0 for every program?)
More generally, how do I make time tell me HOW MUCH RAM WAS USED?
#2: You can compile a C++ program with
g++ program.c++
However, for reasons beyond my comprehension, the result is always named
"a.out". You can tediously fix this using the -o option. Alternatively,
you can write a makefile:
prog1: prog1.c++
g++ prog1.c++ -o prog1
prog2: prog2.c++
g++ prog2.c++ -o prog2
prog3: prog3.c++
g++ prog3.c++ -o prog3
Is there any way of automating this absurd tedium?
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Le 27/01/2011 11:33, Invisible a écrit :
> I've got a couple of Unix questions...
>
>
> #1: Consider the following:
>
> ~$ /usr/bin/time --format="%C\n%E wall time, %P CPU, %M KB maximum"
> ./Prog1
> ./Prog1
> 0:15.27 wall time, 89% CPU, 1608592 KB maximum
>
> The program *actually* used about 400MB of RAM. So WTF is %M actually
> measuring? Because it sure as hell isn't "maximum resident set size of
> the process during its lifetime, measured in Kilobytes".
But there is more than 400MB of data in the RSS.
First, you have the program itself (what is the filesize ?)
Next, all the shared libraries (and their cascades).
And if 400MB is your malloc... there is also the function's stack to
allocate: calling a function with an array or a structure in C++ is
allowed, and if you do not push for a reference, you might get the value
copied on the stack...
Recursion in functions is another deepener.
>
> (Also, why do %D, %K and %X all return 0 for every program?)
15 seconds is a very short time. Also, even if supported on the command
line, the man page states:
"Not all resources are measured
by all versions of Unix, so some of the values might be reported
as zero. "
>
> More generally, how do I make time tell me HOW MUCH RAM WAS USED?
>
What is RAM used for ?
RSS is the answer, for program, lib & data.
>
>
> #2: You can compile a C++ program with
>
> g++ program.c++
>
> However, for reasons beyond my comprehension, the result is always named
> "a.out". You can tediously fix this using the -o option. Alternatively,
> you can write a makefile:
>
> prog1: prog1.c++
> g++ prog1.c++ -o prog1
>
> prog2: prog2.c++
> g++ prog2.c++ -o prog2
>
> prog3: prog3.c++
> g++ prog3.c++ -o prog3
>
> Is there any way of automating this absurd tedium?
Yes.
Use the target naming in your makefile's rules
(have a search about $* $< $> ... in make tutorial)
--
Software is like dirt - it costs time and money to change it and move it
around.<br/><br/>
Just because you can't see it, it doesn't weigh anything,
and you can't drill a hole in it and stick a rivet into it doesn't mean
it's free.
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
>> 0:15.27 wall time, 89% CPU, 1608592 KB maximum
>>
>> The program *actually* used about 400MB of RAM. So WTF is %M actually
>> measuring? Because it sure as hell isn't "maximum resident set size of
>> the process during its lifetime, measured in Kilobytes".
>
> But there is more than 400MB of data in the RSS.
> First, you have the program itself (what is the filesize ?)
> Next, all the shared libraries (and their cascades).
> And if 400MB is your malloc... there is also the function's stack to
> allocate: calling a function with an array or a structure in C++ is
> allowed, and if you do not push for a reference, you might get the value
> copied on the stack...
>
> Recursion in functions is another deepener.
I ran an interactive resource monitor while the program was running, and
saw that free memory decreased by 400MB while the program was running.
That's how I know it used roughly 400MB. (I don't know what it used it
*for*, but I would presume mostly heap space.)
If the figure reported ("1608592") really is in KB, that's 1.6GB - which
far exceeds the available physical memory. That can't be right.
If the figure is actually bytes, then that's 1.6MB - which is *still* wrong.
>> (Also, why do %D, %K and %X all return 0 for every program?)
>
> 15 seconds is a very short time.
It's several eternities for a computer.
> Also, even if supported on the command line, the man page states:
> "Not all resources are measured
> by all versions of Unix, so some of the values might be reported
> as zero. "
Right. So Linux doesn't suppose this information. That's OK.
>> More generally, how do I make time tell me HOW MUCH RAM WAS USED?
>
> What is RAM used for ?
> RSS is the answer, for program, lib& data.
Then why do the answers not match reality?
>> Is there any way of automating this absurd tedium?
>
> Yes.
> Use the target naming in your makefile's rules
> (have a search about $* $< $> ... in make tutorial)
I don't particularly want to spend three weeks reading through the
obtuse reference manual. It would be quicker to just keep typing this
stuff by hand. I just wondered whether somebody already happens to know
the answer to this (presumably) very common problem...
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Le 27/01/2011 15:35, Invisible a écrit :
>> Use the target naming in your makefile's rules
>> (have a search about $* $< $> ... in make tutorial)
>
> I don't particularly want to spend three weeks reading through the
> obtuse reference manual. It would be quicker to just keep typing this
> stuff by hand. I just wondered whether somebody already happens to know
> the answer to this (presumably) very common problem...
Fish, eating, learning,... all that old metaphore.
here a little makefile for gnu-make, but YMMV, to generate png picture
from every dot file in the current directory.
I guess you can adapt it for your c++ compilation.
(hint: dot -o outputfile inputfile)
all: $(patsubst %.dot,%.png,$(wildcard *.dot))
.SUFFIXES: .dot .png
.dot.png:
dot -Tpng -o $@ $<
--
Software is like dirt - it costs time and money to change it and move it
around.<br/><br/>
Just because you can't see it, it doesn't weigh anything,
and you can't drill a hole in it and stick a rivet into it doesn't mean
it's free.
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
>> I don't particularly want to spend three weeks reading through the
>> obtuse reference manual. It would be quicker to just keep typing this
>> stuff by hand. I just wondered whether somebody already happens to know
>> the answer to this (presumably) very common problem...
>
> Fish, eating, learning,... all that old metaphore.
Well yes, if I was likely to use make ever again, learning how it works
might be beneficial. Since I'm most unlikely to ever touch it again...
it's rather a lot of effort for little benefit.
> here a little makefile for gnu-make, but YMMV, to generate png picture
> from every dot file in the current directory.
>
> I guess you can adapt it for your c++ compilation.
> (hint: dot -o outputfile inputfile)
> all: $(patsubst %.dot,%.png,$(wildcard *.dot))
>
> .SUFFIXES: .dot .png
> .dot.png:
> dot -Tpng -o $@ $<
Hmm, never mind. Apparently renaming all the *.c++ files to *.cpp
enables Make to automatically figure out what to do. Go figure.
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Invisible <voi### [at] dev null> wrote:
> #2: You can compile a C++ program with
> g++ program.c++
> However, for reasons beyond my comprehension, the result is always named
> "a.out". You can tediously fix this using the -o option.
How else do you suggest the binary be named? "The same as the source
file" is not a good answer because there may be (and often is) more than
one source file. You can easily compile a multi-sourced program with
"g++ *.cc". The -o parameter exists to tell the compiler the name of
the binary.
Anyways, if you find yourself compiling the same program again and again,
that's exactly what makefiles are for, so you can simply write "make".
> Alternatively,
> you can write a makefile:
> prog1: prog1.c++
> g++ prog1.c++ -o prog1
> prog2: prog2.c++
> g++ prog2.c++ -o prog2
> prog3: prog3.c++
> g++ prog3.c++ -o prog3
> Is there any way of automating this absurd tedium?
A makefile is, basically, what other SDKs call a "project" file. You can
specify dependencies between files and rules on how to build files from
other files (the idea, as with "project" files in other SDKs, is that files
are built only if their source files change rather than every time).
Writing a makefile by hand can be somewhat tedious, but you only have
to do it once. (Also, like most "project" files, it has a lot of flexibility.
Makefiles are not exclusively used to compile programs, but can be used for
a lot of other things where files are created from other files, or simply
programs are run based on certain rules.)
Gnu make offers some shortcuts which you can use to abbreviate some things,
such as for example:
myprogram: source1.cc source2.cc source3.cc
g++ $^ -o $@
Of course that rule is incomplete in that if any of those source files
depends eg. on a header file, it won't take that into account (in other
words, if you change the header file, the program will not be recompiled).
If you simply want it to recompile the program every time you run make,
you can "trick" make to do it by giving a rule which is named differently
from the resulting file, and leaving the conditions out, like:
all:
g++ source1.cc source2.cc source3.cc -o myprogram
(This works because there is no file named 'all' in the current directory,
so make will try to "build" it by running the command. Since the command
doesn't create it, it will do so also the next time you run make, and so on.)
Of course this is good only if you really want to recompile everything
every time.
A full-fledged makefile would build object files from each single source
file, and then link those object files into the final binary. This allows
compiling only those object files that really need it, so if there are
many source files, it will speed up compilation.
Of course the rules for this to work become very complicated, and nobody
in their right minds would write them by hand. There exist tools to
automatically create a makefile from a bunch of source files (think
automake is such a tool), or you could use gnu make in conjunction with
gcc's dependency-generation features to do it with them. I use this
generic makefile a lot for this exact purpose. Simply add it inside the
directory where your source files are, and 'make' will do the rest. (The
only defect is that if dependencies change, this will not notice it. You'll
have to remove the .dep file and it will start working again.)
#------------------------------------------------------------
# List source files (not headers!) and binary name:
SOURCES=$(wildcard *.cc)
BINARY=programname
# Set up compiler and compiler options:
CXX=g++
LD=g++
CXXFLAGS=-Wall -Wextra -pedantic -ansi -O3
LDFLAGS=-s
LDLIBS=
# --- No need to modify anything below this line ---
all: .dep $(BINARY)
$(BINARY): $(SOURCES:.cc=.o)
$(LD) $^ -o $@ $(LDFLAGS) $(LDLIBS)
clean:
rm -f .dep $(BINARY) $(SOURCES:.cc=.o)
.dep:
g++ -MM $(SOURCES) > .dep
-include .dep
#------------------------------------------------------------
--
- Warp
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
On 27/01/2011 03:26 PM, Warp wrote:
> Invisible<voi### [at] dev null> wrote:
>> #2: You can compile a C++ program with
>
>> g++ program.c++
>
>> However, for reasons beyond my comprehension, the result is always named
>> "a.out". You can tediously fix this using the -o option.
>
> How else do you suggest the binary be named? "The same as the source
> file" is not a good answer because there may be (and often is) more than
> one source file. You can easily compile a multi-sourced program with
> "g++ *.cc". The -o parameter exists to tell the compiler the name of
> the binary.
I still don't see why it couldn't default to the name of the source file
for the common case where only one is supplied, but anyway...
> Anyways, if you find yourself compiling the same program again and again,
> that's exactly what makefiles are for, so you can simply write "make".
> A makefile is, basically, what other SDKs call a "project" file. You can
> specify dependencies between files and rules on how to build files from
> other files (the idea, as with "project" files in other SDKs, is that files
> are built only if their source files change rather than every time).
Yes, I know what Make does and why that's useful. It's just that for
what I'm trying to do, it's overkill. All I want to do is be able to
quickly recompile a program each time I edit the source, without having
to type in long complex commands.
> Writing a makefile by hand can be somewhat tedious, but you only have
> to do it once.
...except that every time I add another program, I end up having to add
another line to the Makefile to handle it.
I've got half a dozen trivial little C++ programs, and I want to be able
to quickly recompile any of them. It's frustrating me that it's this
difficult to do something so trivial.
The solution, as I just discovered, is to name the files *.cpp rather
than *.c++; this apparently enables Make's implicit rules to fire. (I
thought *.c++ was one of the "recognised" names, but apparently not...)
> (This works because there is no file named 'all' in the current directory,
> so make will try to "build" it by running the command. Since the command
> doesn't create it, it will do so also the next time you run make, and so on.)
...or you could just mark "all" as a phony target. (Yes, I read that
far. I've actually got a "clean" target in my Makefile, for example...)
> A full-fledged makefile would build object files from each single source
> file, and then link those object files into the final binary. This allows
> compiling only those object files that really need it, so if there are
> many source files, it will speed up compilation.
>
> Of course the rules for this to work become very complicated, and nobody
> in their right minds would write them by hand. There exist tools to
> automatically create a makefile from a bunch of source files
...which is all very interesting, but overkill for what I'm trying to do.
I've played with things like the Makefile for GHC, which supports
compiling the compiler, compiling the compiler with the compiler you
just compiled, running the test suite, building the user manual,
building the library documents, running the standard benchmark set, and
polishing your shoes for you. It's neat that you can do all that, but
it's far beyond my simple needs.
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Invisible <voi### [at] dev null> wrote:
> The solution, as I just discovered, is to name the files *.cpp rather
> than *.c++; this apparently enables Make's implicit rules to fire.
Not a good solution because you are not getting warnings nor
optimizations.
--
- Warp
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Invisible wrote:
> I still don't see why it couldn't default to the name of the source file
> for the common case where only one is supplied, but anyway...
It could. It doesn't.
> quickly recompile a program each time I edit the source, without having
> to type in long complex commands.
That's what !! or the up arrow key is for. Lacking that, that's what a shell
script is for. If your program consists of a single file, you don't need
Make at all.
>> Writing a makefile by hand can be somewhat tedious, but you only have
>> to do it once.
>
> ...except that every time I add another program, I end up having to add
> another line to the Makefile to handle it.
No you don't. That's what wildcards are for.
> I've got half a dozen trivial little C++ programs, and I want to be able
> to quickly recompile any of them. It's frustrating me that it's this
> difficult to do something so trivial.
It's a one-line shell script to recompile every .c++ file into the
corresponding executable file name.
>> Of course the rules for this to work become very complicated, and
>> nobody
>> in their right minds would write them by hand. There exist tools to
>> automatically create a makefile from a bunch of source files
Actually, the primary problem with makefiles is actually C's bizarre
#include rules, where source files depend on other source files which aren't
evident from looking at the source files.
--
Darren New, San Diego CA, USA (PST)
"How did he die?" "He got shot in the hand."
"That was fatal?"
"He was holding a live grenade at the time."
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Darren New <dne### [at] san rr com> wrote:
> Actually, the primary problem with makefiles is actually C's bizarre
> #include rules, where source files depend on other source files which aren't
> evident from looking at the source files.
Never miss a chance to belittle C-like languages.
--
- Warp
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |