![]() |
|
#1
|
|||
|
|||
User defined headersQuote:
This is certainly open to some debate. My position is that one should NEVER use quotation marks to include files, as this makes the code dependent on the location of the file. By using the angle bracket method of including files, the build environment then becomes responsible for resolving file path details. This is particularly true when a system starts to grow and the location of the files need to be "reorganized." Trying to edit all of the code becomes a maintenance problem, whereas editing a simple one liner in a Makefile or IDE-world is a breeze. Consider even a simple program with 5 classes each defined in their own .h and each implemented in their own .cpp. For this argument, let's say that the entire source code resides in some subdirectory such as: mycode/src/*.cpp *.h ...and you wanted to modify your file structure so that you can add several dozen new classes to something like: CPP / C++ / C Code:
...can you imagine the increased difficulty in editing potentially hundreds of files that may include myproject/src/Widget1/Widget1.h? All of your test cases would need to be modified, all of your SDK files and potentially a lot of documentation "scripts" would all need to be edited to reflect the file structure reorganization. What happens when you get into a project where you're sharing your source with someone else? For simplicity, let's say that they don't need anything but your Widget1.h and Widget1.cpp. But maybe they want their headers centralized? Obviously, editing just one .cpp file would be easy, but if they had to do it every time you provided any code, it wouldn't be an ideal method of making new friends, huh? What if you're using an editor that automatically maintains Makefile dependencies as you "add" files to your "project?" The hardcoded path information is going to be painful at best. Like all of those SDK examples that have: CPP / C++ / C Code:
This is about as criminal as "user defined" header file include statements can get. What it really shows is that our programmer is simply inexperienced and naive. How much easier it is for several layers deep worth of "example" code to use: CPP / C++ / C Code:
And then specify in the Makefile or build script what is needed to resolve the dependency? You know what's better than that? DOS programmers who use capital filenames for every header file and then lowercase letters in the filenames when the move to case-sensitive file systems with case-insensitive build environments! :davis: |
|||
|
#2
|
|||||||||
|
|||||||||
Re: User defined headersHi Davis, you have some very good points here. I understand where you are coming from. In general I disagree though.
Quote:
Quote:
Quote:
Keep in mind the functionality of the "head.h" file is implementation dependant. Other compilers are free to redefine this search algorithm, but I believe most 'top end' compilers at least follow the process Borland uses. Quote:
Make files do alleviate a lot of this situation, as do the project files in an IDE. But if care is taken up front (the plan ahead syndrome) most of the drawbacks can be alleviated. This comes from experience more than anything else. Quote:
Quote:
Quote:
Quote:
Quote:
I must have been a bad DOS programmer. I can't think of one capital letter I've ever used in a header declaration. __________________
Cow: You're a lawyer too? Mooseblood (mosquito): Ma'am, I was already a bloodsucking parasite. All I needed was a briefcase! |
|
#3
|
|||||||||||||
|
|||||||||||||
Re: User defined headersQuote:
I think of this as being a good thing. I see that you feel that it is a bad thing. I disagree with you in a semantics kind of way that the compiler needs to be set up. Most of the preprocessing features of toolchains have some kind of default search path for system headers. They are generally stored in some kind of configuration mechanism for the preprocessor. Any modern IDE should be able to be configured for "default" paths that are not necessarily "system header" paths. Quote:
Yes! ...except not necessarily, but at least something to "that" effect. By adding and maintaining -I<path> information (whether through makefiles or IDE projects), you add somewhat to the rigidity of enforcing individuals to maintain any non-standard build "methods." Additionally, for simple programs, the only thing one needs to do is include the current path in the list, for example: -I. Quote:
This is not a good solution for system developers who write libraries used by others. I think that you're thinking solely from an app-developer perspective. Imagine that you're writing a full-featured library such as something along the lines of a MySQL C-API...to just use something of similar relevance. Your C-API is going to standardize rather quickly and at some point, you're going to reduce feature-creep so that your /usr/include/mysql/mysql.h file doesn't keep adding new #include "anotherfile.h" in it. However, your "next release" of the API will likely have some bug fixes and code improvements that are most likely localized to the .c files with minimal .h file intrusion. Can you imagine if you used a "headers/file.h" include statement in your C file? ..especially if the user elected to install the headers in /usr/include/mysql? Millions of systems allow the user to choose where they install portions of a subsystem. For example, Qt for the X Window system allows one to specify where the includes, libraries, documentation, etc. are all individually installed. It is common practice to include these files using angle bracket notation. The same reasoning for this makes it easier when working with several versions of a product app. Quote:
Are you thinking about DOS/Windows-centric compilers for that particular platform "family?" C was written on UNIX and made to work on DOS based on the limitations of DOS by companies like Borland, who are now all but extinct when it comes to total market share. Quote:
I'm not sure that I'm following your logic here. Are you trying to say that if you wanted to include elements from 20 unrelated projects into a single "uses these" app that it would be more difficult to use <include.file> versus "include.file"? Quote:
How many people seriously build "real world code" using no form of makefile or other build system such as that provided by most IDEs? For that matter, how many people (on Windoze) actually invoke the commandline version of their compiler? Don't they most often rely on at least a batch file with common commandline switches to feed to the tool binaries? Quote:
Flexibility is the key to success in an ever rapidly changing development environment. I believe that by adding the angle brackets, one gains the flexibility of file placement by enforcing that the build environment resolve the problem. It is very Bruce Lee: flex-e-bility wid-out flex-e-bility! All professional developers use some form of automated build system for anything but the most trivial of applications. By including the -I details in the automated system, one gains flexibility to relocate the files endlessly and easily maintain and hide the details through a configuration dialog and/or automated build system interface. Quote:
...not if the "centralized" headers location is not centralized to the "system," but centralized to the particular set of code being discussed. Then, a quick flick of the mouse is all that it takes to change between versions of the headers, such as might be done when reviewing and maintaining builds of several projects from several different developers. Quote:
Yeah? ...no. Because if you have the following path: CPP / C++ / C Code:
...and src.c looks like: CPP / C++ / C Code:
and x.h in the somepath/src/include #defines COUNT as 1 and x.h in the somepath/src path #defines COUNT as 2, what will the printf print? CPP / C++ / C Code:
The same goes for: CPP / C++ / C Code:
...how does one specify which version of x.h we want to use? ...so that we get the version that defines COUNT as 1? If we swap the comment so that the angle bracket version is enabled instead of the quotation marks version: CPP / C++ / C Code:
...easy to tell that we're not doing something that the build needs in order to proceed properly. CPP / C++ / C Code:
...builds properly and produces i = 2, as expected. CPP / C++ / C Code:
...builds properly and produces i = 1, as expected. Quote:
It is nice to be able to find some common ground for agreement, it makes areas of disagreement seem so much less disagreeable! Quote:
...I have to say that what I've shown here is an obvious form of disagreement, since something is really lost by using the quote form as it does not include the bracket form of header specification in its entirety, rather, it searches the defaults but not necessarily the specified paths as specified using -I, which I've shown here. Perhaps your view of this is implementation-specific to your preprocessor? Maybe my view of it is equally specific to my preprocessor, however, I can say that either way, if the angle bracket method is used, we BOTH can "enjoy" the features of both worlds with minimal pain. Quote:
I'm thinking that with 30 years of programming experience, that you are going to already know the difference between a "system" header and one in an application you're working on/with regardless of the quotation marks or angle brackets...if not, well, welcome to C 28 years later! Quote:
Even still, the lowercase declarations were fairly prevalent...though the file names were nearly always in all uppers. Coming to DOS programming from UNIX was always very painful for at least that reason and the 8.3 limitation...and because DOS was such a wannabe OS compared to a "real" system...you definitely got what you paid for in it! :davis: |
|
#4
|
|||||||||||||||
|
|||||||||||||||
Re: User defined headersI don't think we're really far off in our concepts, but we're approaching the same idea from two different angles, two different ideas that aren't gelling.
The problems I see in your arguments are from my definition of what I think you're saying, not from yours. I believe this is where our interpretations aren't meshing. Quote:
If I'm right in my new assessment, I agree that is definitely an acceptable way to define your project. I feel less need to go thru that definition process though for a small project (it's actually more of a pain for, say, a single source project), but for middle to large projects it makes sense. Quote:
IOW, the user can place your header files anywhere he wants and his compiler finds them -- your code is already compiled and has no need for the headers at all so your directory structure does not need to be replicated. Quote:
Quote:
Quote:
By the way, when I mentioned the -I switch, that is the system definition for the compiler and points to the compiler standard headers. Your code did not follow that fact which may be why I disagree with your scenario. Quote:
search local directoriesI can't think of any compiler I've run across that doesn't use this definition. Maybe there are some after all. Good to know. Quote:
Quote:
Bottom line for me is I simply don't see the problem with the quote-form of an include file. Knowing where the file comes from is simply part and parcel of C/C++ programming. I find it useful. Others may not. Same as the 'global' and 'namespace' contoversies. Both sides are have merit -- choose your poison. __________________
Cow: You're a lawyer too? Mooseblood (mosquito): Ma'am, I was already a bloodsucking parasite. All I needed was a briefcase! |
|
#5
|
|||||||||||||
|
|||||||||||||
Re: User defined headersWaltP,
I hope you don't mind, but I've chosen to respond out of the original order of your reply. Quote:
I don't think that this topic is really about how I code/build projects or how you code or build projects. I think that it is more one of how should people include files using the quotation marks or angle brackets choice(s). Obviously, our personal/professional experiences will bring added benefit to such a discussion, but can we try to focus on what should the "mainstream" (80/20 rule) programmer be using? I don't know what the largest percentage of currently active C and C++ programmers use to edit their related project files, but I'm willing to bet that there are a reasonably large percentage employing some form of GUI-based editor and/or "developer suite" such as emacs that may or may not have use a GUI "proper." I think that it is also safe to say that for any non-trivial project, some sort of makefile or other (perhaps IDE-project oriented) "automated" build system is used. If we can agree on these "ground rules" for establishing a precedence for what constitutes the 80-percentile group, we will, I think, establish a basis for making a recommendation regarding the topic. Should we use angle brackets or quotation marks to include "non-system" headers? Obviously, individual programmer preferences are going to dictate what actually happens in the field, but if we were to somehow come up with a hypothetical "GIDForums C/C++ Coding Standard," what would it contain on this topic? That is what I hope this discussion answers--based on a reasonable application of logic AND based on the majority of user categories rather than either my or your specific preferences. Quote:
Section 4.11.1 of K&R 2nd Edition says: "If the filename is quoted, searching for the file typically begins where the source program was found; if it is not there, or if the name is enclosed in < and >, searching follows an implementation-defined rule to find the file."This very clearly suggests that everything to do with file inclusions of both types are left up to the implementation of the specific C preprocessor. Words like typically and implementation-defined serve to drive that point home. Granted, there are some commonality among some vendors, but we would necessarily need to ascertain the 80% of compilers used in order to truly follow the premise that I earlier set out, correct? Barring the availability of meaningful compiler usage demographics, we can probably suppose fairly closely given a "short list" of compilers. Obviously, individual compiler "families" and "versions" would grow the list exponentially, but shall we suffice it to say at least the following (for Intel-compatible PCs, only): MS C/C++/VC++/.NET/etc. Borland GNU GCC/G++ (including MinGW, Cygwin, DJGPP, etc.) Watcom Intel ..again, this was intentionally a short list with the intent of defining the 80%. Surely there are countless others. The above listed compilers are in no particular order or precedence. We can also make an assumption that the two most prevalent Intel-based operating systems where these compiler choices might be deployed would be: MS DOS/Windows variants Linux/Other x86-based UNIX systems, including BSD, Solaris, etc. If we say that this group of compilers and target operating systems comprise the "expected" 80% (if not more) of all users for Intel-based systems, we will have a very short list of platforms whereby we can very easily apply some tests and come up with a good recommendation/80-20 rule for include-file syntax. Do you agree? Please feel free to supplement the list as you see fit based on the criteria given. However, if we are in general agreement, the Intel x86-based compiler that I specifically used and mentioned in my reply was definitely in the 80% category and it is GNU gcc/g++. Considering that there appears to be a notably sized group of student programmers posting and following threads on this forum, and many of them indicate that they're using Dev-C++ with MinGW (a GNU variant), I'd suggest that perhaps one of them can indicate whether that target follows the same rules as I've seen in my tests. Quote:
Whenever I create a library, DLL or API I always distribute source code to be compiled by users as sample or example code meant to illustrate the use of the library, DLL or API. Oftentimes, this example code is cut-n-pasted into new projects that become the foundation for those projects. Additionally, I find that by providing very clear, well-commented and documented example code, technical support issues dramatically diminish. Quote:
I also produce a good amount of open source software, so oftentimes the entire sources are provided in the distribution. What I am saying is that by using #include "filename" versus #include <filename> then YES the source code does become very dependent on where the header files are located and, when angle brackets are used exclusively, NO the source code is not dependent on the location of the header files, BUT the build environment must be (if not using the defaults) modified to reflect the actual path of the header(s). Quote:
I fully understand the point that you're trying to make here, but I don't think that you're following my points. When team dynamics come into play and the USER categories of the files are not necessarily "end users" for a lib/dll/api, but also other developers who will be working with the sources, the dependency incurred by the quotation marks is transfered to them! Consider the role of someone who manages builds and you have say 10 developers each providing you with sources. (We've decided to remove configuration management software to another topic, right?) As these developers send you files, IF they use the quotation marks method of including files, are they not forcing their path dependency on whomever must build and assemble/test the collective sources? If they are using the angle brackets method, aren't they saying "put them anywhere you want and let your build system figure out where they are, because these sources don't care as long as they can somehow get to them?" Quote:
Differing versions of softwares are going to introduce the possibility of an unlimited number of headers with the same name. Consider for a moment when using a 3rd party library such as Qt. Let's say that you are considering moving from version 3.x to 4.x. Let's say that you've built a number of projects that use Qt. So, on a whim, you decide to try building one that was built against Qt v3.x with the latest and greatest v4.x. Let's say that you have placed your files as such: CPP / C++ / C Code:
Obviously, you wouldn't want to use the following: CPP / C++ / C Code:
...in your code. We can safely say that the above path is not going to be considered a likely candidate for any "default search" preprocessor in either the 80 or 20 percent cases, right? So, what we do is we just include what we need as follows: CPP / C++ / C Code:
...and then we let the build system "manage" the actual location of the necessary includes BUT also, for whatever particular version we may be using at the moment. Now, instead of being a Qt "end user" category of user, you happen to be a Qt "developer" category of user. Let's say that your header file named qt-my-killer-widget.h needed qwidget.h among other things. You certainly wouldn't use #include "somepath/include/qwidget.h" because ever single version would require somepath to be explicity changed in every possible source file including your example code that shows end users and other developers how to use your killer widget. If we can agree on this simple kind of "revolving user categories," then we can safely say that the same user will, over time, be one or more of possibly several different "categories" of users. In fact, in any organization where code reuse is practical, there can be NO use of quotation marks include files AT ALL in source code, is my position. Part of this is due to the nature of "moving versions," "revolving user categories" and many others, including using configuration management software. Quote:
...there is no big deal, in fact, that is what is recommended. When -I doesn't work is the big deal...and it definitely does not work (as intended) when one uses quotation marks versus angle brackets. It can be made to work by placing all of the desired include paths under the current working directory, but I think that we can both agree that that is not a viable alternative to simply recommending and preferring to use angle brackets over quotation marks in code. Quote:
Let me quote from GNU's info: CPP / C++ / C Code:
Here is what Microsoft's MSDN web site says about the /I switch: CPP / C++ / C Code:
In other words, I'd say that the handling of -I is somewhat tool-dependent. As we can see here, the MS compiler always searches the local path whereas GCC (and others) handle it differently. Quote:
This is probably a viable topic for another discussion, however, considering that Microsoft doesn't even use VSS for their code repository, and that there are numerous free and paid CM software products available that were not mentioned, we should probably carefully frame any future thread regarding CM so that the numerous issues related to that world can be targeted individually or in related subgroupings. Quote:
It may be useful to some percentage of the population, but, IMO, its drawbacks definitely do not justify using it AT ALL EVER...with the only possible exception being quick hacks...and ESPECIALLY for those using MS tools that automatically check the current path. Quote:
Are you seeing things any differently now? Quote:
I'm not exactly sure what your statement means, but if you're suggesting that the "indication" given by using angle brackets versus quotation marks is somehow a "big clue" as to where the include files are located, I have to disagree...ESPECIALLY if MS tools search the system directories AND the local path. Do you see my point? Quote:
I'm not sure what tangential reference you're making here except that there are often more than one "popular" opinion on several different issues. Part of why I'm here is so that other programmers are able to make informed choices based on fundamentally sound standards and practices. In reality, how often is NEVER or ALWAYS a "good thing?" In programming, it does tend to come up a bit more regularly than in "real life," doesn't it? Like "always free your heap allocations." Right? Always initialize your pointers/variables before using them...etc. Well, why would I suggest that there is NEVER a good (enough) reason to use angle brackets in include statements? Obviously this is going to be a controversial issue simply due to the fact that there are two choices for include directive syntax. I also realize that this "convention" that I'm asserting, is not very popular compared to all of the millions of cases where quotation mark directives are freely used throughout code. I offer it as something for others to consider adopting in their own code so that they are more easily maintained, reassembled into other directory structures and modified over time. If change is the only constant, we live in a world of great change. Code and where the code lives is bound to change over time, too. By using angle brackets, we free the code from being bound to a specific location. In every debate, there will be many good reasons for looking at both sides of the coin in some kind of equal-but-opposite ways. One could easily argue that the intended functionality of a code base is based on its exact header and by defining exactly where it must live in the .c/.cpp file, we've taken steps to ensuring that it is always there. My response would be that if I change the physical file contents I have as much opportunity to improve it or screw it up. Demanding location specificity in the code only makes the code that much harder to change (and therefore manage) over time. I'll step off of the soapbox for now. I don't want to drag the dead horse through the mud, too. :davis: |
|
#6
|
|||||||||||||||
|
|||||||||||||||
Re: User defined headersI'm going to try and make this shorter than normal, and hit only high points.
I'd also like to have other's opinions on this topic. Many of you have been programming long enough to lend your expertise... Quote:
Quote:
Quote:
implementation-defined for both forms. The committee copped out and didn't even specify what K&R suggested. Quote:
MS-C++and a couple others that show up very irregularly Quote:
WindowsAgain, others infrequently. My choices are based on postings here and a little on other boards I've seen. Quote:
IMO, for this discussion, we must leave these distributions out. Source is generally not supplied. So we must limit this discussion to in-house projects (or aquired projects if you need to expand the sample), not purchased add-ons. Quote:
Therefore, the developers are not forcing their path structure, the project has defined the path structure for the developers. Teams should not have Lone Rangers doing their own thing. And using angles, you still have to put the headers in one of a set of specific dirs. You can't just put them just any ol' place in either scenario. Quote:
Quote:
Let's assume you put the header with the source for convenience, and do not use the -I switch to add to the system search -- as I believe you shouldn't under most situations. If you then follow the GNU/Borland scenario, no matter which compiler you use the project will build. Any and all quoted-headers will be found in all 3 compilers. But if you use the angle-header form, only M$ will compile the project because the angle-header format for Borland and GNU do not search the local directory. Quote:
Quote:
Your summary remarks (scroll back to previous post) are very good. I can't argue with much there. Maintainability is extremely important as well as changability as you point out. If we can limit the breakability of changes, a good portion of the battle is won. If angle-headers work to limit that breakability -- adopt it. If angle-headers are more logical for your programming style -- adopt it. After all, coding style is a personal choice (within reason) and even within a team environment there is room for personalization of style. Again, I invite others to comment on this topic. __________________
Cow: You're a lawyer too? Mooseblood (mosquito): Ma'am, I was already a bloodsucking parasite. All I needed was a briefcase! |
|
#7
|
|||
|
|||
Re: User defined headersQuote:
That is my POINT entirely! You keep calling the quotation marks some kind of specific "rule-based" include search and the angle brackets some kind of "system" include search. Yet, by your admission, they are both entirely left up to the specific system implementation. Don't you see that it is only by your convention that you prefer quotation marks? You prefer them based on your experiences using your style of coding. As I mentioned in the first place was that this is not meant to be a discussion about what I prefer or what you prefer but what is the right recommendation for aspiring programmers! Okay, so then I introduced some common (more than 80%?) platforms and compilers. Of these, only the recommendation that best suits that body will fit into the 80% (or more) group, right? Of those: MS Borland GNU (Dev-C is not a compiler, but uses a GCC-based compiler) ...are the only ones that fit into the 80% (or more group), right? Let's find out what people are using in www.gidforums.com. Quote:
...I don't think that there are going to be very many x86/Intel-compatible Macs just yet. Didn't they only recently announce that they're going to be running in x86? Quote:
Again, you didn't read what I wrote...(and this time I wrote what I meant <grin>) You are also letting your own subset of the world be the reflecting point you offer for the recommendation that I'm suggesting we promote to others...irrespective of our personal preferences. I'm asking you to separate yourself from the problem and come up with as objective of a recommendation based on the facts, not on your or my coding styles and preferences. There exists millions and millions of software that is distributed in source form. Everything from massive, large-scale projects like OpenOffice.org to operating systems and much, much more and everything in between ALL distributed with complete source code. Is that more or less than 10% of all software? I don't know. There are more than 200 supported Linux distributions but only really three or four supported Windows distributions (not counting language specific variants). So, if operating systems software for desktops is one category of all software, Linux alone represents a 50:1 ratio of softwares that are distributed with source compared to softwares distributed without sources. Add BSD, Herd and any others, like Minix...etc., and you've got a fairly large number of individual products (not total quantities of a single product in use) that are distributed with all of the sources to their libs, DLLs, API, etc. Sourceforge has 112,990 (hit their site for a live update) registered, OPEN SOURCE projects that all release the complete source to their libs, DLLs, API, etc. BUT...I didn't even say that I release the SOURCE CODE TO THE DLL/lib/API, etc. I said that I always release source code with it to demonstrate how to use it in the form of examples/samples. My SAME POINT about angle brackets and quotation marks apply EQUALLY to the sources that I do release. Here is the point that I think you're missing. Again, you are used to your narrowly defined conventions and you're not opening your mind to the possibilities outside of your convention and comfort zone. If the typical behavior of the 3 compilers listed (MS/Borland/GCC) are all relatively similar in that they search the current path for include directive files, then using the quotation marks requires the files to be path relative to the sources...in fact, it requires the headers to live somewhere in or under the directory where the sources are installed. WHETHER or not the sources are THE source for the lib/dll/api or whether the sources are just examples of how to use the lib/dll/api. In effect, the sources are dictating where the headers must live. Oh sure, you can copy them somewhere else, but then if you're working on multiple versions of a lib/api/dll/etc., how screwed up does your world get as a result? If the angle brackets are used, the files may be placed anywhere and USUALLY only a single file needs to be edited in order to reflect the change. This STYLE more readily accepts change. That is my point. And, if there is anything true in this world, it is that things are going to change. Okay, let's go in a slightly different direction. You would probably not consider the Linux kernel sources to be "system" include files, right? Especially if you were working on several different versions of the Linux kernel, under some path mysources/files/linux_kernel/versions/1.2/...etc. Okay...so can we agree that the Linux kernel source is mostly C code? (You're area of specialty, right?) Can we agree that there are MANY different developers working on the Linux Kernel sources and who have worked on it in the past several years? Okay...so why would a project that large, that involved so much to the point that it ranks at least a solid #2 in all of the OSes used for writing code on boards like this and many others...so why would that project not use a single quotation mark style #include directive in over 1800 instances of #include? CPP / C++ / C Code:
|