Ways of building the code

Programming, for all ages and all languages.
OSMAN

Ways of building the code

Post by OSMAN »

Hello!

""My way of compiling the C-code of my kernel is that I have a line, which joins all of my C code files into one before "make", in my build-script.
So I don't have to use any #include:s.""
Then it compiles the asm and the C into two object files and links them into ELF.

Is the thing inside the ""tetramarks"" good or bad or between?
proxy

Re:Ways of building the code

Post by proxy »

seems like a very silly way to do things especially as the project grows over time.

really the usual way is like this:


gcc -c file1.c -o file1.o
gcc -c file2.c -o file2.o
gcc -c file3.c -o file3.o


and then:

gcc file1.o file2.o file3.o -o program

now, with kernels you are gonna probably way a special linker script in that last step or at the very least some linker options, but the point is this is the norm.

but why you may ask.

well if i have a 20,000 line kernel (mine is about this at the moment). If i modify ONE line of code, i only have to recompile the .c which contained it and then relink. But your example would require a complete recompile of the kernel.

It is a HUGE time saver to modularize the code and minimize how much of it is recompiled when you make changes.
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re:Ways of building the code

Post by Solar »

There is no rule against doing it this way, but header files and #include's are your friend. The idea is to declare a couple of logically related functions and their parameters (plus usually adding some comments as to what they're doing) in a .h header file, and have all the implementation details in the .c "implementation" file.

This is how, like, 99.9% of all software is written.

I think it's funny that 99.9% of the remaining 0.1% seem to be people writing kernel code. You should be quite fluent in software development before you come up with the idea to write your own OS, so that writing headers and using #include's in a smart way should be second nature...
Every good solution is obvious once you've found it.
zloba

Re:Ways of building the code

Post by zloba »

Separate compilation also allows to isolate things in each source file , so they don't crowd the namespace. (you can have #defines, "static" helper functions, data, etc. that are not seen outside a source file)

Header files then provide "interfaces" and indicate dependencies between source files.

Of course, you can do that in any case, by wrapping "private" stuff of each source file in a separate namespace (if you can compile it in C++ mode)..

BUT: there's a nice thing (for C++) you can get by including all source files together, which you don't normally get otherwise. (at the cost of full recompile)

with separate compilation of classes, if you use a class whose method bodies are in a different source file, you will have to duplicate method prototypes from the header in the implementation source file with bodies, which is an ugly piece of redundancy.

with all sources getting lumped together, you can just implement methods either in the class body or outside, as you like.

(IMO. I haven't tried this, but I think it should work. I may want to try it sometime.)
JoeKayzA

Re:Ways of building the code

Post by JoeKayzA »

zloba wrote: with separate compilation of classes, if you use a class whose method bodies are in a different source file, you will have to duplicate method prototypes from the header in the implementation source file with bodies, which is an ugly piece of redundancy.

Won't you have the same 'problem' in C too? I never considered this a problem - when you have declaration and implementation in two different places, somehow you'll have to show which method implementation belongs to which declaration, and providing the prototype again is a straight forward method to me...
zloba wrote: with all sources getting lumped together, you can just implement methods either in the class body or outside, as you like.
Well, I don't know your programming style and how well you come along with it, so to everyone his own. (I hope this proverb is valid in english)

But IMO you should at least keep consistency among your sources. Meaning that you should either implement everything in the class body (like in Java) or everything outside.

No rant - just comment ;)

cheers Joe
zloba

Re:Ways of building the code

Post by zloba »

2 JoeKayzA: :)
Won't you have the same 'problem' in C too?
Yes, same 'problem' in C, with function prototypes.
somehow you'll have to show which method implementation belongs to which declaration, and providing the prototype again is a straight forward method to me...
Straightforward? Yes. Elegant? I'll say no. First, I have to retype (or copy and paste) the prototypes in implementation. Then, prototypes change, and need to be updated in the implementation. Redundancy isn't good.

And it didn't have to be this way in C++. In my language, I can just "implement" a prototype, interface, virtual method, etc. like this:
(<prototype> $imp <body>)
In C++, it could've been smth. like:
<prototype>.implement [ name ] [ (renamed-args) ]{ <body> };
Well, I don't know your programming style and how well you come along with it
That was just a speculation on one _possible_ benefit of the lumping together. _Not_ advocacy of immediately switching to said lumping. I did say that I haven't tried this..
But IMO you should at least keep consistency among your sources.
I agree.
(I hope this proverb is valid in english)
Sounds valid enough to me. (I'm not a native english-speaker)
Cjmovie

Re:Ways of building the code

Post by Cjmovie »

so to everyone his own
To Each his own is the 'real' version, IIRC.

And it really should be:
To Everyone their own.
User avatar
Candy
Member
Member
Posts: 3882
Joined: Tue Oct 17, 2006 11:33 pm
Location: Eindhoven

Re:Ways of building the code

Post by Candy »

Solar wrote: This is how, like, 99.9% of all software is written.

I think it's funny that 99.9% of the remaining 0.1% seem to be people writing kernel code.
I consider it pretty likely that people that don't like the default coding style(s) also don't like the default OSes.
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re:Ways of building the code

Post by Solar »

zloba wrote: ...prototypes change, and need to be updated in the implementation. Redundancy isn't good.
Do they? I mean, do prototypes change? In my experience, new prototypes get added, but existing ones usually don't change, because of the possibility of existing code using the old interface.
And it didn't have to be this way in C++. In my language...
C++ is not a laboratory language. It was designed to be as compatible to C as possible. Of course many things could have been done in a much cleaner way, but would C++ have been as successful if it had been significantly different than C?
I can just "implement" a prototype, interface, virtual method, etc. like this:
(<prototype> $imp <body>)
Means, no-one can look at the function prototypes at a glance (without using external tools), because they are always mingled together with their implementations...
In C++, it could've been smth. like:
<prototype>.implement [ name ] [ (renamed-args) ]{ <body> };
Straightforward? Dunno, still used to the C/C++ ways. Elegant? Not more so than the way things are...
That was just a speculation on one _possible_ benefit of the lumping together. _Not_ advocacy of immediately switching to said lumping. I did say that I haven't tried this..
If you're in Rome, do as the Romans do. C/C++ code traditionally has declarations in seperate header files, apart from their implementation.
Every good solution is obvious once you've found it.
JoeKayzA

Re:Ways of building the code

Post by JoeKayzA »

Cjmovie wrote: To Each his own is the 'real' version, IIRC.
Oh, right, sorry. ::)

Means, no-one can look at the function prototypes at a glance (without using external tools), because they are always mingled together with their implementations...
And this is actually why I don't like to edit Java sources with a plain text editor. You have to scroll for miles to find a method prototype, and without syntax highlighting, it can get even more stressing. Therefore I prefer 'advanced' source editors for Java (an IDE, admittedly), which at least support collapsing and expanding of code blocks.

But I believe that C and C++ have different reasons for seperating prototypes in header files than just readability, in the first place it's probably more the 'compile first, then link'-issue. But I think Solar probably has more experience in these things... ;)

cheers Joe
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re:Ways of building the code

Post by Solar »

JoeKayzA wrote:
But I believe that C and C++ have different reasons for seperating prototypes in header files than just readability, in the first place it's probably more the 'compile first, then link'-issue. But I think Solar probably has more experience in these things... ;)
Data encapsulation. For one, it's a good programming practice, especially in OO, and I was honestly surprised to learn that Java made such a bad job at it. I frankly don't care how a function is implemented 95% of the time. They basically "outsourced" that job to javadoc...

Second, consider the times when OSS / GPL wasn't yet the hype it is today, and code quite frequently was shipped without source (gasp!). You'd have some blackbox named libsomething.a or libsomeother.o, containing all the nice functions you need.

Sure, you don't need prototypes to use the functions therein, but it makes for a better error checking. You'd also like to use symbolic constants instead of magic numbers, and there might be some macros of use with that library, too. All that is made available in the header file, without the library vendor disclosing its valuable library innards.

Java does some of this with smart tools (reading the prototypes from bytecode), and doesn't do other things at all (macros, although nothing keeps you from running cpp over Java sources ;) ). Don't forget that C and Java are several generations apart, not only in language design but also in the available hardware power.
Every good solution is obvious once you've found it.
JoeKayzA

Re:Ways of building the code

Post by JoeKayzA »

Solar wrote: Java does some of this with smart tools (reading the prototypes from bytecode), and doesn't do other things at all (macros, although nothing keeps you from running cpp over Java sources ;) ).
I suspect static constant values should substitute macros, they are linked at load time too, just as all the classes and methods. But I already noticed several rants about the lack of a preprocessor, and AFAIK, there are even some inofficial Java preprocessors out there....it's probably all about style and habits. And somehow I get a bad feeling that this will get moved into the 'General Programming' section soon... :D

cheers Joe
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re:Ways of building the code

Post by Solar »

JoeKayzA wrote: I suspect static constant values should substitute macros, they are linked at load time too, just as all the classes and methods.
If you think of "macros" only as [tt]#define foo 42[/tt]. Macros can be much more (and a great way of obfuscating your source or introducing subtle bugs, too). ;)
...it's probably all about style and habits.
I didn't rant. I tend to take a language as-is, and try not to fall for the "you can write FORTRAN in any language" kind of mindset. It's just that Java and C++, while looking pretty similar at first glance, are two completely different approaches to programming.
And somehow I get a bad feeling that this will get moved into the 'General Programming' section soon... :D
Now there's an idea. ;)
Every good solution is obvious once you've found it.
zloba

Re:Ways of building the code

Post by zloba »

Do they? I mean, do prototypes change?
They very much do. Design changes, arguments change. I agree it doesn't happen too often (usually), but it does.
new prototypes get added, but existing ones usually don't change, because of the possibility of existing code using the old interface.
If the project has been published and in wide use, yes. But how about small projects? Rapid prototypes, pre-release? Internal interfaces? etc. What should I maintain compatibility with?
"Change is the only thing that is constant" (c) not sure about source and exact wording.
It was designed to be as compatible to C as possible.
Where does that break downward compatibility? Sure the new code won't work with plain-C compilers, but neither will methods, namespaces and lots of other things.
would C++ have been as successful if it had been significantly different than C?
How does that make it significantly different more than, say, type overloading or any other C++ feature? You just can't compile these things in C mode, period. Not without expressing them in terms C can understand.
Means, no-one can look at the function prototypes at a glance
You can copy the prototype anywhere as a comment, for the sake of documentation.
Or make duplicating a prototype _optional_.
Or allow a stand-alone precondition on the prototype, so you can put it anywhere it if it pleases you. (even in the user code)
This does it for documentation _and_ can be used to raise the red flag when the prototype changes and you forget to update it at a body. (Instead of silently compiling it with the old prototype and then producing an obscure linker error)

Ok, the way C/C++ does it with separate prototypes and bodies accomplishes that (mostly), but only for the bodies, and you get no choice, whether you need this or not.
I tend to take a language as-is, and try not to fall for the "you can write FORTRAN in any language" kind of mindset.
Are you saying that existing languages are final and no new ones should ever be created?
I've been taking languages "as-is" for some time now, and I'm fed up with all the little things combined.
FYI, it's not FORTRAN, far from it. Nor a laboratory language. It is intended to replace C/C++ and to be as practical (more so), barring immediate compatibility and general acceptance. How's that for FORTRAN?

I agree, C++ is what it is, generally accepted and all, no one argues. But that doesn't mean I have to stick with it. New OS, new language, new everything.
AR

Re:Ways of building the code

Post by AR »

zloba wrote:
would C++ have been as successful if it had been significantly different than C?
How does that make it significantly different more than, say, type overloading or any other C++ feature? You just can't compile these things in C mode, period. Not without expressing them in terms C can understand.
You completely missed the point here, the point is not that C++ code can be built with a C compiler but that C code can be built with a C++ compiler. At the time everything was in C so C++ was designed to allow incremental adaption to C++ features.
I tend to take a language as-is, and try not to fall for the "you can write FORTRAN in any language" kind of mindset.
Are you saying that existing languages are final and no new ones should ever be created?
I've been taking languages "as-is" for some time now, and I'm fed up with all the little things combined.
FYI, it's not FORTRAN, far from it. Nor a laboratory language. It is intended to replace C/C++ and to be as practical (more so), barring immediate compatibility and general acceptance. How's that for FORTRAN?

I agree, C++ is what it is, generally accepted and all, no one argues. But that doesn't mean I have to stick with it. New OS, new language, new everything.
You do realise that that is similar to the point of the D language.
Post Reply