What are the pros and cons of specifying an include prefix in the source file versus in the search path parameter of the compiler?
When a C or C++ library comes with several headers, they are usually in a specific folder. For example, OpenCV provides cv.h
and highgui.h
in a opencv
folder.
The most common way to include them is to add this opencv
folder to the search path of the pre-compiler (e.g. gcc -I/pathto/opencv
), and simply include the headers by their filename in the source file (e.g. #include <cv.h>
)
There is an alternative, as it is quite frequent that folders containing headers are with others (e.g. in /usr/include
or some path common to the development team) in a parent folder. In this case, it is enough to specify the header folder in the source file (e.g. #include <opencv/cv.h>
), if the parent folder is already in the path.
The only problem I can think of with this alternative is the case of a system where all the headers are in a sin开发者_JAVA技巧gle folder. However, this alternative prevents ambiguities (e.g. if two libraries have a vector.h
header), makes it easier to set up another build system, and is probably more efficient regard to the search of the header file by the pre-compiler.
Given this analysis, I would tend toward the alternative, but a vast majority of code I found on internet use the first. For example, Google returns around 218000 results for "#include <cv.h>"
, versus 79100 for "#include <opencv/cv.h>"
. Am I missing advantages of the common way, or disadvantages of the alternative?
My personal preference is to have <opencv/cv.h>
.
Why ? Because I am human, with a limited brain, and much more important things to do than remember that cv.h
comes from the opencv
library.
Therefore, even though the libraries I work with are always in dedicated folders, I structure them as:
<specific library folder>/include/<library name>/...
This helps me remember where those headers come from.
I have known people saying it was useless, and that IDEs would bring you straight to the file anyway... but
- I don't always use an IDE
- I don't always want to open each include file merely to know which libraries this particular file is tied to
It also makes it much easier to organize the include list (and group related includes together).
They have slightly different purposes, and I think need to be used carefully.
Consider the fact that in the -I
case it was /pathto/opencv
. You're suggesting possibly #include <opencv/cv.h>
but you'd never write #include </pathto/opencv/cv.h>
. There's a reason for that, which is that you expect cv.h
is always in a directory called opencv
, because that's how it's always released, whereas pathto
is just where that library's files happen to have been installed on your machine (or on your distribution, whatever).
Anything that could conceivably differ depending where your code is being compiled, should be in the include path, so that it can be configured without modifying your source. Anything that is guaranteed to be the same wherever that particular cv.h
is used can appear in the source, but it doesn't have to, so we need to decide whether we want it there.
As you've already noticed, it's useful to have it there as a disambiguator, especially for a file with a two-character name, but if you think that someone might want to put cv.h
in a different place, then you should leave it out. That's pretty much the trade-off you're making - the header should always be in an opencv
directory, but is it worth it to you to rely on that as a guarantee, as the price of disambiguating?
I would guess the main problem with using #include <opencv/cv.h>
is that you don't necessarily want to add an entire parent path.
Taking an example where it has been installed to /usr/local
when using the option with the full path, you'll need to add -I/usr/local/include
to your command line. That could have all kinds of side effects.
E.g. for a completely different application, someone may have installed GNU iconv libraries there. Then suddenly, your application, which is also doing #include <iconv.h>
is grabbing the headers from the standalone iconv library, instead of the implementation in glibc.
Obviously these are problems that do crop up from time to time, but by including more specific directories, you can hopefully minimise them.
Reasons for the first version:
- you are not always able to install the headers/library in a standard path. Some time you do not have root access.
- you do not want to pollute the path adding all the path for all the libraries you have installed.
- for example you can have 2 version of the same library installed (in your case openCV) and you want some of your projects to be compiled with one library and some other with the other library. If you put them in the path then you get a name clash. For me this is one of the main reason (exactly for OpenCv I have version 1.x and 2.x installed and some projects compiled with 1.x and some with 2.x).
精彩评论