Here is an article by Walter Bright that explains what the C++ compiler is doing: https://www.digitalmars.com/articles/b54.htm <https://www.digitalmars.com/articles/b54.html>l Walter Bright is the creator of the first C++ compiler (if I remember right this was the Zortech C++ compiler, later acquired by Symantec).
aleksey...@gmail.com schrieb am Sonntag, 15. November 2020 um 20:12:49 UTC+1: > Yeah, that's a good point. A C unit that is using f() won't > necessarily include f's implementation if it is defined somewhere > else. It may create a (weak?) reference to f() and leave the rest to > the linker. However to compile correctly it would *normally* include a > header where f() is declared to at least check that f() is accessed > using the correct interface, so f's declaration would normally be > pulled into a unit. > > In C++ what to include into a unit and what not to include is a bit > more complicated especially if templates are involved (which is > usually the case), but perhaps such details are out of the scope of > this mailing list. > > But yeah, i didn't realize that my email might be misleading in that > regard, sorry about that. > > вс, 15 нояб. 2020 г. в 18:19, Robert Engels <ren...@ix.netcom.com>: > > > > Object files do not contain dependencies except for code that the > compiler inlines. It has linkage referees that are resolved during linking. > > > > On Nov 15, 2020, at 8:05 AM, kev kev <kevthem...@gmail.com> wrote: > > > > Reading Alekseys description, it does seem to be making a bit more > sense. The C/C++ compilers use a "file" as a compilation unit. A file is > converted to an object file which must contain all of its dependencies. So > the includes will need to copy all of the code that they are importing into > the file that is being compiled. > > > > In Golang, the object file is more of a blackbox which contains only the > necessary data that is needed. I'm assuming that "necessary" relates to > type checking and symbol resolution mostly. > > > > It seems that one key difference is that Golang uses a package as a > compilation unit, while C++ uses a file. If Golang used a file also and not > a module structure, then it seems that similar issues or a significant > decrease in performance would be observed. You would have more object files > for one and there would be more dependencies between files. > > > > > > > > On Saturday, 14 November 2020 at 05:57:27 UTC aleksey...@gmail.com > wrote: > >> > >> There is no direct relationship between headers and object files in C > >> or C++. Compilation process is two stage: > >> > >> 1. Source files are compiled into object files > >> 2. Object files are linked together into executable of sorts > >> > >> (Actually it's a three stage process, but i'm going to describe it > >> using two stages). > >> > >> Stages are isolated from each other and to some extent autonomous. > >> Object files are kind of intermediate representation of source code > >> that is later used to produce machine code. I'm sure someone can > >> correct me on this, but for the sake of simplicity, i think it's OK to > >> think of them as of IR. > >> > >> When *compilation unit* is compiled into an object file, it is also > >> separated from other units. To compile it separately from other units > >> all relevant source code has to be pulled into the current unit and > >> compiled. So `#include <something.h>` doesn't include just > >> something.h, it includes something.h, then all includes that > >> something.h includes and so on. This is a process similar to > >> amalgamation of source code, everything is copied into one place and > >> then compiled as a single unit. After all units are compiled, they > >> might be joined together by a linker either into a static library, > >> dynamic library or executable. > >> > >> This is actually more sophisticated than that, but it does allow you > >> to do some cool stuff like you can compile your source code into > >> objects, then ship object files and then link them elsewhere. In fact, > >> static libraries are just a bunch of object files packed together, but > >> headers are still required because you need symbol names to refer to > >> on source code level, therefore libraries are shipped with headers: > >> you compile with headers and then link with objects. > >> > >> Since it's the separate stages, you could, for instance, write your > >> own headers for 3rd party objects, think open source headers for > >> closed source DirectX SDK. > >> > >> This description is very superficial and doesn't cover a lot of what > >> is really going on. The process is very flexible and allows to do all > >> kinds of stuff in various combinations. Alas this process is also not > >> very fast and requires some costly steps like you need to pull all > >> required source code into a single unit to compile it. > >> > >> Modern C++ is also using a lot of templates, even if you're not > >> writing templates, you're going to use templates from the standard > >> library and to use templates you need to transform (instantiate) each > >> template into concrete code and then (simply put) compile instantiated > >> template as regular non-templated source code. Because every > >> compilation unit is being "amalgamated", this process has to be > >> repeated for every unit, which also takes some time. > >> > >> There is such thing as C++ modules, but they are quite new > >> (standardized like a month ago) and not yet widespread. I think they > >> should be more similar to Go *packages* when source code files are > >> logically joined into a single entity and for that entity another > >> intermediate representation is created which is called BMI (binary > >> module interface) even though it doesn't have to be binary, so > >> sometimes it's called CMI (compiler module interface). > >> > >> This CMI is basically a compiler cache, a package, or in terms of C++, > >> a module interface, can be compiled once and then reused to compile > >> object files without recompiling the same source code for every unit. > >> > >> Regarding how packages compilation actually works in Go - this is an > >> interesting topic. I'm afraid i won't be able to explain it more or > >> less correctly and i would be glad to read about it too. > >> > >> сб, 14 нояб. 2020 г. в 04:17, kev kev <kevthem...@gmail.com>: > >> > > >> > > >> > Thanks for the answer. If C/C++ has object files, is it not possible > to see “something.h” and then fetch the corresponding object file? > >> > > >> > With go, if I import “package something” and that package imports > another package called “package bar” then at some point I will need to > compile “bar” and “something”. This to me is like your header example. > >> > > >> > I think you are maybe saying that this traversal is only done once > for golang and the information is stored in an object file? While in C, the > header traversal is done each time I see include? > >> > On Saturday, 14 November 2020 at 00:14:41 UTC Kevin Chowski wrote: > >> >> > >> >> C/C++ also has object file caching (depending on how your build is > set up, I guess). In C/C++ the issue is that you need to possibly open a > large number of header files when you import any header file. > >> >> > >> >> For example, if I write a file "main.c" which imports "something.h", > which in turn imports "another.h" and "big.h", and compile just main.c, the > compiler has to open all three header files and include them in the parsing > of main.c in order for the compilation to correctly move forward. In Go, > the compiler arranges things such that it only has to open one file per > package that is imported. The post you linked goes into greater detail, so > I will avoid duplicating the details for now, but feel free to ask a more > specific question and I can try to answer. > >> >> > >> >> There's a bit of nuance there, which the post also goes into: Go's > strategy ends up requiring that some package much be compiled before any > package which imports it is compiled. In C/C++ the ordering is a little > more flexible due to the more decoupled nature of header files, meaning > that theoretically more builds could occur in parallel. But I suspect that > in your average Go program the dependency tree would still allow you to > execute a large number of builds in parallel. > >> >> > >> >> Also note that the article claims this is "the single biggest > reason" Go compilation is fast, not the only one. There are lots of > smaller, yet important, reasons as well. For example, parsing the language > is pretty straightforward because it is not very complex, and linking the > final binary together is continually being optimized. Plus there are no > turing-complete meta-language features like the templates C++ compilers > have to deal with ;) > >> >> > >> >> As for your following, the whole set of files in some package are > the compilation unit, at least as far as I understand the terms. This is > because if a.go and b.go are both in the same package (e.g. in the same > directory), code in a.go can call code in b.go without explicitly declaring > anything. So before the code in a.go can be fully compiled into an object > file, b.go must be considered as well. > >> >> On Friday, November 13, 2020 at 3:54:34 PM UTC-7 kev kev wrote: > >> >>> > >> >>> I recently read the post by Rob Pike about language choices for > Golang: https://talks.golang.org/2012/splash.article#TOC_5. > >> >>> > >> >>> The seventh point refers to how Golang handles dependencies. It > mentions an "object file" for packages that a _dependent_ reads. > >> >>> > >> >>> Below I go through my interpretation of this section: > >> >>> > >> >>> Example: > >> >>> > >> >>> package A imports package B. > >> >>> > >> >>> When I compile package A, package B would have already been > compiled. What package A receives is not the AST of package B, but an > "Object file". This object file only reveals data about the publicly > accessible symbols in that package. From the example, if B had a private > struct defined inside of it, this private struct would not be in the object > file. > >> >>> > >> >>> This part seems to make sense for me, hopefully I did not make any > mistakes. > >> >>> > >> >>> It seems that the speedup compared to C/C++ is because the object > file is created once per package, while in C/C++ you need to re-compile the > thing you are including each time? > >> >>> > >> >>> Followup question: > >> >>> > >> >>> Is a single file a compilation unit or is it a package? > >> >>> > >> >>> Thanks > >> >>> > >> > -- > >> > You received this message because you are subscribed to the Google > Groups "golang-nuts" group. > >> > To unsubscribe from this group and stop receiving emails from it, > send an email to golang-nuts...@googlegroups.com. > >> > To view this discussion on the web visit > https://groups.google.com/d/msgid/golang-nuts/2e237e13-37c9-4741-8ea1-67f813923fafn%40googlegroups.com > . > > > > -- > > You received this message because you are subscribed to the Google > Groups "golang-nuts" group. > > To unsubscribe from this group and stop receiving emails from it, send > an email to golang-nuts...@googlegroups.com. > > To view this discussion on the web visit > https://groups.google.com/d/msgid/golang-nuts/1f55ed1f-de3f-4950-8b1f-c81feaaa8772n%40googlegroups.com > . > > > > -- > > You received this message because you are subscribed to the Google > Groups "golang-nuts" group. > > To unsubscribe from this group and stop receiving emails from it, send > an email to golang-nuts...@googlegroups.com. > > To view this discussion on the web visit > https://groups.google.com/d/msgid/golang-nuts/774661CD-0F92-4F72-ABA8-03F0B585E3C8%40ix.netcom.com > . > -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/7334c3e6-3245-4708-85f8-ae26368a3557n%40googlegroups.com.