I have some .h files as follows (on Linux)
Source/Server/connect.h
Source/Server/message.h
...
I am developing another application that needs the two .h files but is in a different directory
Source/App2/..
How can I include the connect.h file in the App2 application, considering that I use perforce and everyone else working on the application would have their own copy so adding an absolute path to the include library might not be a good idea but im not sure.
EDIT:
I use a proprietary build mechanism for building the code so will not be able to specify gcc options directly.
You can #include a relative path to the files:
#include "../Server/connect.h"
or you can add a flag to tell the compiler to look in the other directory. For gcc you can use -I../Server; for Visual C++ you can use /I"../Server"; other compilers, I'm sure, have their own flags for this purpose.
I think the second is better in most cases, since it allows you to move your projects around while only requiring you to modify the include path in one place (the makefiles or property sheets).
What about adding include search path to he compiler, for gcc it's -I switch.
I suggest removing paths from the #include statements. As others have stated, put the paths into the parameters to the compiler. Resolve the path differences in the makefile or use environment variables (may need to do both).
My experience is that files will move. Anything that doesn't use relative paths will break the build (which is very bad).
in addition static relative paths, you can also play with preprocessor chicanery. One technique I saw used at Adobe for cross-platform code, was to do something like this:
/* globalplatform.h */
#ifdef MAC
#define PLATFORM "../Platform/Mac/MacPlatform.h"
/* custom standard IO etc */
#define STDIO "../Platform/Mac/io/stdio.h"
#define CTYPE "../Platform/Mac/io/ctype.h"
#endif
#ifdef WIN32
#define PLATFORM "../Platform/Win/WinPlatform.h"
#define STDIO <stdio.h>
#define CTYPE <ctype.h>
#endif
/* etc */
#ifndef PLATFORM
#error undefined PLATFORM
#endif
/* some C file */
#include "globalplatform.h"
#include PLATFORM
#include STDIO
/* don't need CTYPE, no penalty */
While the platform problem isn't your problem, you can define the relative paths based on build configuration if you want to and the config changes happen in one place instead of many and client files only pull in what they need. The down side is that any tools you use for browsing header files (right-click and so on) are hosed.
You can change the compiler directives as above, or modify the path within your code (either relative or absolute).
I would suggest that you consider the best locations for headers and object files (and libraries) for all your projects and set that up.
If you have standard include and lib locations you'll simplify the development down the road
Related
I am coding in C++ using the Visual Studio 2019 IDE.
I have followed the convention that every file #includes project files using the exact path. For example:
#include "ProjectName/FolderName2/HeaderName2.h"
#include "ProjectName/FolderName/src/HeaderName1.h"
I have also followed the convention of including the path in my #ifndef header guards:
#ifndef PROJECTNAME_FOLDERNAME_FILENAME_H
#define PROJECTNAME_FOLDERNAME_FILENAME_H
//...
#endif
This is the style suggest by the Google Style Guide.
However, as I am coding, I may want to change folder names. For example, I may decide that ProjectName is not a correct description of the contents of the folder and that I should change the name to ProjectName2. This change, however, requires correcting header guards and each #include that uses ProjectName in the path description. This problem becomes significantly worse if I totally reorganize my code.
Are there (automatic) tools to make this easier? Is #includeing the exact path (from the solution folder) the way to go?
So I'm currently working on something that uses OpenCL. The OpenCL spec provides the users with a directive which must be included before the inclusion of the header (cl.h)
#define CL_TARGET_OPENCL_VERSION 110
Which basically defines the version they want to use. Suppose I'm making a library and I want my users to define this instead of me defining this inside my files. What I did was.
-----main.cpp---
#define CL_TARGET_OPENCL_VERSION 110
#include "library.h"
-------x---------
----library.h-----
#ifdef CL_TARGET_OPENCL_VERSION
#pragma message("def")
#endif
#ifndef CL_TARGET_OPENCL_VERSION
#pragma message("ndef")
#endif
.... include other headers.
--------x---------
And the compiler prints both def and ndef messages. And the OpenCL library also throws a warning that it's undefined. I thought that the library header would get substituted into main and it'd only print the def message. Is there anything I understood wrong?
I'm particularly confused as to where does the preprocessor start? If it starts from main.cpp and goes from top to down, then it surely has defined the macro. After that it sees the library inclusion, then it should only print the def message but it prints both.
This leds me to believe the preprocessor does scan the header file before including it in main? Dunno the reason why. Also I have assured that the library header isn't included elsewhere.
One interesting thing I noticed was, if i did this
-----helper.h---
#define CL_TARGET_OPENCL_VERSION 110
-------x---------
----library.h-----
#include helper.h
#ifdef CL_TARGET_OPENCL_VERSION
#pragma message("def")
#endif
#ifndef CL_TARGET_OPENCL_VERSION
#pragma message("ndef")
#endif
.... include other headers.
--------x---------
It prints the def message "twice". If anybody can explain all this I'd be grateful.
EDIT:- The files I'm compiling are main.cpp library.h and library.cpp
Library.cpp includes library.h from the start as usual. Maybe this other cpp is causing the problem?
In C/C++ programs, the compiler handles each .c and .cpp file separately.
The compilers build each source file (NOT the header files, only .c and .cpp files) independently from each other (this source files are called compilation unit).
Thus, when your main.cpp is built, the compiler finds the #define CL_TARGET_OPENCL_VERSION 110 you have added on top of the main.cpp file, emiting the defmessage.
But when the compiler builds the library.cpp file, it does not find the version define, so it emits the ndef message.
So, following this explanation, it is completely normal that in your last case, when you add the define to the .h file, the compiler emits the def message twice, once for the main.cpp file and once for the library.cpp file.
Now, the problem is where should you add the define, in order to have the program built consistently, with the same version for all the .cpp files.
Usually, all the IDEs have some configuration page where you can add global defines, for all the project, which are "inserted" into all the compilation units before everything else. So when the IDE calls the compiler, it passes the same defines to all the compilation units. You should add this kind of defines in this page.
In your IDE (I am using Code::Blocks, v 17.12), you can find this page in the menu: Project / Build Options
For each type (Debug or Release), you have to go to the tab Compiler Settings, and there to the sub tab #defines. There you can add global defines, which can be different if you are building in Debug or in Release mode (of course, if you set the same in both modes, they would be the same).
Once you have added your define here, please, remove it from the main.cpp, library.h and any other place where you may have added it, in order to avoid duplicities.
From the comments about portability:
You have several options:
Always use Code::Blocks: this would be the easiest way, since you can pass the Code::Blocks project along with the source files, and everything would be already setup.
Use cmake, which is a script build system, where you can set defines and so in the same way as using an IDE. cmake is much widely used than Code::Blocks, so maybe it is a better option.
Add a new options.h header file, where you set all the defines, and include it to all your .c/.cpp. This setup has the additional benefit that for different systems, changing only the options.h file the build can be completely different. This is a manually setup of what the IDE is doing. It has the advantage that does not rely on external tools, but the disadvantage that you have to remember to add it in all the new .cpp files added to the project.
My recommendation is go with cmake, just as the others have said.
Prefer using #ifndef XXXX_h #define XXXX_h #endif over #pragma once
If your #include search path is sufficiently complicated, the compiler may be unable to tell the difference between two headers with the same basename (e.g. a/foo.h and b/foo.h), so a #pragma once in one of them will suppress both. It may also be unable to tell that two different relative includes (e.g. #include "foo.h" and #include "../a/foo.h" refer to the same file, so #pragma once will fail to suppress a redundant include when it should have.
This also affects the compiler's ability to avoid rereading files with #ifndef guards, but that is just an optimization. With #ifndef guards, the compiler can safely read any file it isn't sure it has seen already; if it's wrong, it just has to do some extra work. As long as no two headers define the same guard macro, the code will compile as expected. And if two headers do define the same guard macro, the programmer can go in and change one of them.
#pragma once has no such safety net -- if the compiler is wrong about the identity of a header file, either way, the program will fail to compile. If you hit this bug, your only options are to stop using #pragma once, or to rename one of the headers. The names of headers are part of your API contract, so renaming is probably not an option.
(The short version of why this is problematic to use #pragma is that neither the Unix nor the Windows filesystem API offer any mechanism that guarantees to tell you whether two absolute pathnames refer to the same file.)
I work on a C++ program which I develop on my personal Ubuntu 15.04 machine which eventually has to run on openSUSE 13.1 at work. To make it work on both systems I carefully chose the libraries and the versions to use.
Now I have a problem with the includes. I want to use Qwt 6, which is available on both distributions. The location of the header files differs, though. On Debian they are at /usr/include/qwt/qwt_*.h but on openSUSE they are at /usr/include/qwt6/qwt_*.h. My code currently has #include <qwt/qwt_plot.h>. This does not work on openSUSE since I would have to insert that 6 there.
The easiest solution that I currently see is just including either directory using CMake and then just writing #include <qwt_plot.h> in the source code. However, I think that this is not a really nice solution since those subdirectoryies of /usr/include are there to provide namespaces. Just adding all directories to the include path will mangle those together and might even lead to conflicts.
Is there a nice way to solve this?
In fairness: This is for a project I am paid to work on.
In CMake you can configure platform checks like you could for autoconf. The idea is that you include a config.h file that always exists but use tools to generate that file in each platform. You can check how here but as a summary you can have a config.h.in file with the checks you want to make and use in your headers.
#cmakedefine HAVE_QWT_H
#cmakedefine HAVE_QWT6_H
You then have CMake check if the headers are present and process that file into a final config.h file. In the CMakeLists.txt file you could have the following.
INCLUDE (CheckIncludeFiles)
CHECK_INCLUDE_FILES (qwt/qwt_plot.h HAVE_QWT_H)
CHECK_INCLUDE_FILES (qwt6/qwt_plot.h HAVE_QWT6_H)
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)
Finally, in your headers, you include the config.h and use the macros to conditionally include one header or another.
// always included
#include "config.h"
// conditionally include headers based one macros from config.h
#ifdef HAVE_QWT_H
#include <qwt/qwt_plot.h>
#elseif HAVA_QWT6_H
#include <qwt6/qwt_plot.h>
#else
#error QWT headers required and not present in supported locations
#endif
I'm working on a project that system headers can appear in "" and also in <>
for example: "io.h" and <io.h>
I need to determine if the included header is a customer one or not.
someone knows if there is a way to do it?
Aside from "asking the compiler", there is no trivial way to determine if "io.h" or <io.h> is taken from a local directory or somewhere in the standard headers. For example, a program will compile perfectly happily with #include "iostream".
The main difference is that the compiler will look FIRST in the local directory for the file "io.h" when using "io.h", where if you use <io.h> it will look in the include directories specified as "system include directories". However, there is nothing saying that system include directories does not include "current directory" in one way or another.
You can use g++ -M myfile.cpp to list what include files are used in the file "myfile.cpp". Unfortunately, as far as I can tell, there is no such option for Visual Studio.
Edit: The MS compiler does indeed support a similar feature using the /showinclude option.
Take a look to the documentation of your compiler, for example the MS C++ compiler will check system includes after local with quotes (so #include "io.h" will get the system include if there are no io.h local header files), but it won't look locally for angled brackets:
http://msdn.microsoft.com/en-us/library/36k2cdd4.aspx
I guess that you will have to manually check for project files if there are names collisions for include files.
I have a very large codebase (read: thousands of modules) that has code shared across numerous projects that all run on different operating systems with different C++ compilers. Needless to say, maintaining the build process can be quite a chore.
There are several places in the codebase where it would clean up the code substantially if only there were a way to make the pre-processor ignore certain #includes if the file didn't exist in the current folder. Does anyone know a way to achieve that?
Presently, we use an #ifdef around the #include in the shared file, with a second project-specific file that #defines whether or not the #include exists in the project. This works, but it's ugly. People often forget to properly update the definitions when they add or remove files from the project. I've contemplated writing a pre-build tool to keep this file up to date, but if there's a platform-independent way to do this with the preprocessor I'd much rather do it that way instead. Any ideas?
Little Update
Some compilers might support __has_include ( header-name ).
The extension was added to the C++17 standard (P0061R1).
Compiler Support
Clang
GCC from 5.X
Visual Studio from VS2015 Update 2 (?)
Example (from clang website):
// Note the two possible file name string formats.
#if __has_include("myinclude.h") && __has_include(<stdint.h>)
# include "myinclude.h"
#endif
Sources
SD-6: SG10 Feature Test Recommendations
Clang Language Extensions
Create a special folder for missing headers, and make that folder to be searched last
(that is compliler specific - last item in "INCLUDES" environment variable, something like that)
Then if some header1.h can be missing, create in that folder a stub
header1.h:
#define header1_is_missing
Now you can always write
#include <header1.h>
#ifdef header1_is_missing
// there is no header1.h
#endif
Generally this is done by using a script that tries running the preprocessor on an attempt at including the file. Depending on if the preprocessor returns an error, the script updates a generated .h file with an appropriate #define (or #undef). In bash, the script might look vaguely like this:
cat > .test.h <<'EOM'
#include <asdf.h>
EOM
if gcc -E .test.h
then
echo '#define HAVE_ASDF_H 1' >> config.h
else
echo '#ifdef HAVE_ASDF_H' >> config.h
echo '# undef HAVE_ASDF_H' >> config.h
echo '#endif' >> config.h
fi
A pretty thorough framework for portably working with portability checks like this (as well as thousands others) is autoconf.
The preprocessor itself cannot identify the existence of files but you certainly can use the build environment to do so. I'm mostly familiar with make, which would allow you to do something like this in your makefile:
ifdef $(test -f filename && echo "present")
DEFINE=-DFILENAME_PRESENT
endif
Of course, you'd have to find an analog to this in other build environments like VisualStudio, but I'm sure they exist.
Another possibility: populate a directory somewhere with zero-length versions of all of the headers you wish to optionally include. Pass a -I argument to this directory as the last such option.
The GCC cpp searches its include directories in order, if it finds a header file in an earlier directory it will use it. Otherwise, it will eventually find the zero-length file, and be happy.
I presume that other cpp implementations also search their include directories in the order specified.
You could have a pre-build step run that generates an include file that contains a list of #defines that represent the names of the files existing in the current directory:
#define EXISTS_FILE1_C
#define EXISTS_FILE1_H
#define EXISTS_FILE2_C
Then, include that file from within your source code, and then your source can test the EXISTS_* defines to see whether a file exists or not.
So far as I know cpp does not have a directive regarding the existence of a file.
You might be able to accomplish this with a bit of help from the Makefile, if you're using the same make across platforms. You can detect the presence of a file in the Makefile:
foo.o: foo.c
if [ -f header1.h ]; then CFLAGS+=-DHEADER1_INC
As #Greg Hewgill mentions, you can then make your #includes be conditional:
#ifdef HEADER1_INC
#include <header1.h>
#endif
Contrary to some claims here and on the internet, Visual Studio 2015 does NOT support the __has_include feature - at least according to my experience. Tested with Update 3.
The rumors may have arisen from the fact that VS 2017 is also referred to as "Version 15"; VS 2015 is instead referred to as "Version 14". Support for the feature seems to have been officially introduced with "Visual Studio 2017 Version 15.3".
I had to do something similar for the Symbian OS. This is how i did it:
lets say you want to check if the file "file_strange.h" exists and you want to include some headers or link to some libraries depending on the existance of that file.
first creat a small batch file for checking the existence of that file.
autoconf is good but an over kill for many small projects.
----------check.bat
#echo off
IF EXIST [\epoc32\include\domain\middleware\file_strange] GOTO NEW_API
GOTO OLD_API
GOTO :EOF
:NEW_API
echo.#define NEW_API_SUPPORTED>../inc/file_strange_supported.h
GOTO :EOF
:OLD_API
echo.#define OLD_API_SUPPORTED>../inc/file_strange_supported.h
GOTO :EOF
----------check.bat ends
then i created a gnumake file
----------checkmedialist.mk
do_nothing :
#rem do_nothing
MAKMAKE :
check.bat
BLD : do_nothing
CLEAN : do_nothing
LIB : do_nothing
CLEANLIB : do_nothing
RESOURCE : do_nothing
FREEZE : do_nothing
SAVESPACE : do_nothing
RELEASABLES : do_nothing
FINAL : do_nothing
----------check.mk ends
include the check.mk file in your bld.inf file, it MUST be before your MMP files
PRJ_MMPFILES
gnumakefile checkmedialist.mk
now at compile time the file file_strange_supported.h will have an appropriate flag set.
you can use this flag in your cpp files or even in the mmp file
for example in mmp
#include "../inc/file_strange_supported.h"
#ifdef NEW_API_SUPPORTED
LIBRARY newapi.lib
#else
LIBRARY oldapi.lib
#endif
and in .cpp
#include "../inc/file_strange_supported.h"
#ifdef NEW_API_SUPPORTED
CStrangeApi* api = Api::NewLC();
#else
// ..
#endif