Reputation: 2183
Let's say I have 10 *.hpp and *.cpp files that I need to compile a code. I know that I will need those same files for many different codes. Can I create a "package" with those files that would allow me to simply write:
#include <mypackage>
instead of:
#include "file1.hpp"
#include "file2.hpp"
...
#include "file10.hpp"
I wouldn't then need to write a makefile every time I need this "package".
To be more precise, I use Linux.
Upvotes: 61
Views: 112881
Reputation: 255
This method works for both C++ and C. They have the same building process.
Say you want to use the function hello
defined in the file hello.cpp
, and you want to use it via a library.
//file hello.cpp
#include <iostream>
void hello(void) {
std::cout<<"hi"<<std::endl;
}
The convention is to first create another file hello.h
and declare the functions (and variables, if any), for hello.cpp
.
In C and C++ definition is different from declaration. The rule is define once and declare as many times as you want, and declaration shall precede usage.
//file hello.h
#ifndef HELLO // C macro guard to prevent this file being included more than once
#define HELLO // you can ignore them
void hello(void);
#endif // end of guard
Here is main.cpp
//file main.cpp
#include "hello.h"
int main () {
hello();
return 0;
}
So this is your file structure:
src
|- main.cpp
|- hello.cpp
|- hello.h
After writing the files we are only half way done. We still need to compile and link the source file. There are two options of linking : static linking and dynamic linking.
g++ hello.cpp -c -o hello.o // compile to object file
g++ main.cpp -c -o main.o // compile main.cpp to object file
g++ main.o hello.o -o a.out // linked object file and produce executable
Now you may execute the executable a.out
.
Dynamic library ends in so
. The convention is to name it as libCUSTOMNAME.so
. When linking, pass the flag -lCUSTOMNAME
instead of the file name.
g++ -fPIC hello.cpp -o hello.o // -fPIC produces position independent code.
g++ -shared -Wl,-soname,libhello.so hello.o -o libhello.so // produce the dynamic library file
g++ main.cpp -L$(pwd) -lhello -Wl,-rpath=$(pwd) // compile and link main file
In the last line of the code, $(pwd)
is shell code substitution for path of current directory. -L
specifies the location of the dynamic library file, -Wl,rpath=
specifies run time path.
Building C and C++ source code is troublesome. This job is even more compilicated for large projects. The Linux Kernel has over 10000 lines of makefile and a custom build system, Kbuild,.
Many tools are developed to solve this problem, such as gnu make, cmake, gmake, ninga, meson, etc. But in my opinions these tools are not very helpful, as they tries to solve a complicated problem by introducing more complications and idiosyncrasies.
For more information, see
Upvotes: 0
Reputation: 101446
A collection of CPP sources (H files and CPP files) can be compiled together in to a "library," which can then be used in other programs and libraries. The specifics of how to do this are platform- and toolchain-specific, so I leave it to you to discover the details. However, I'll provide a couple links that you can have a read of:
Creating a shared and static library with the gnu compiler [gcc]
Walkthrough: Creating and Using a Dynamic Link Library (C++)
Libraries can be seperated in to two types: source code libraries, and binary libraries. There can also be hybrids of these two types -- a library can be both a source and binary library. Source code libraries are simply that: a collection of code distributed as just source code; typically header files. Most of the Boost libraries are of this type. Binary libraries are compiled in to a package that is runtime-loadable by a client program.
Even in the case of binary libraries (and obviously in the case of source libraries), a header file (or multiple header files) must be provided to the user of the library. This tells the compiler of the client program what functions etc to look for in the library. What is often done by library writers is a single, master header file is composed with declarations of everything that is exported by the library, and the client will #include
that header. Later, in the case of binary libraries, the client program will "link" to the library, and this resolves all the names mentioned in the header to executable addresses.
When composing the client-side header file, keep complexity in mind. There may be many cases where some of your clients only want to use some few parts of your library. If you compose one master header file that includes everything from your library, your clients compilation times will be needlessly increased.
A common way of dealing with this problem is to provide individual header files for correlated parts of your library. If you think of all of Boost a single library, then Boost is an example of this. Boost is an enormous library, but if all you want is the regex functionality, you can only #include
the regex-related header(s) to get that functionality. You don't have to include all of Boost if all you want is the regex stuff.
Under both Windows and Linux, binary libraries can be further subdivided in to two types: dynamic and static. In the case of static libraries, the code of the library is actually "imported" (for lack of a better term) in to the executable of the client program. A static library is distributed by you, but this is only needed by the client during the compilation step. This is handy when you do not want to force your client to have to distribute additional files with their program. It also helps to avoid Dependancy Hell. A Dynamic library, on the other hand, is not "imported" in to the client program directly, it is dynamically loaded by the client program when it executes. This both reduces the size of the client program and potentially the disc footprint in cases where multiple programs use the same dynamic library, but the library binary must be distributed & installed with the client program.
Upvotes: 99
Reputation: 11
simply all you'd have to do is create a .h or .hpp file that has
#ifndef MAIN_LIB_H
#define MAIN_LIB_H
#include "file1.hpp"
#include "file2.hpp"
#include "file3.hpp"
...
#include "file10.hpp"
#endif
make the file called whatever I would choose main_lib.h because of the ifndef, and just
#include "DIRECTORY PATH IF THERE IS ONE/main_lib.h"
in the main file. No need for anything else if you were using visual studios. Just build then press CTRL + F5.
Upvotes: 1
Reputation: 10947
On Linux:
g++ FLAGS -shared -Wl,-soname,libLIBNAME.so.1 -o libLIBNAME.VERSION OBJECT_FILES
where
FLAGS: typical flags (e.g., -g, -Wall, -Wextra, etc.)
LIBNAME: name of your library
OBJECT_FILES: objects files resulting from compiling cpp files
VERSION: version of your library
Upvotes: 6
Reputation: 24576
Yes and no.
You can write an include-all header so that #include "myLib.h"
is sufficient, because you include all those headers through the single header. However, that does not mean that the single include is enough to have the content of the 10 '.cpp' files linked to your project automagically. You will have to compile them into a library and link that single library (instead of all the object files) to the projects that use "myLib.h". Library binaries come as static and dynamic libraries, the files are typically named .lib
and .dll
(windows) and .a
and .so
(linux) for static and dynamic libraries, respectively.
How to build and link such libraries depends on your build system, you might want to loke those terms up on the net.
One alternative is to get rid of the .cpp
files by defininig all the functions in the headers. That way you won't have to link the additional library, but it comes at the cost of increased build times, because the compiler will have to process all those functions every time you include the header directly or indirectly into one of your translation units.
Upvotes: 2
Reputation: 129314
Assuming your "file1.hpp" and "file2.hpp" etc are closely related and (nearly) always used together, then making one "mypacakge.h" that contains the includes of the other components is a good idea (it doesn't in and of itself make it into a library - that is a different process altogether).
If they are NOT closely related and/or used together, then you shouldn't have such a "mega include", because it just drags in a bunch of things that aren't needed.
To make a library involves building your code once, and either generating a .lib file or a shared librar (.dll or .so file). The exact steps to do this depends on what system you are using, and it's a little too complicated for me to explain here.
Edit: To explain further: All of the C++ library is actually one library file or shared library file [along with a number of header files that contain some of the code and the declarations needed to use the code in the library]. But you include <iostream>
and <vector>
separately - it would become pretty awful to include EVERYTHING from all the different C++ library headers in one <allcpplibrary>
, even if it was a lot less typing involved. It is split into sections that do one thing per headerfile. So you get a "complete" set from one header file, but not a too much other things you don't actually need.
Upvotes: 2
Reputation: 70213
If a client needs all ten headers to actually make use of your "package" (library), that's pretty bad interface design.
If a client needs only some headers, depending on which parts of your library are being used, let the client include the appropriate headers, so only a minimal set of identifiers are introduced. This helps scope, modularization, and compilation times.
If all else fails, you can make an "interface header" for external use, which is different from the ones you use internally for actually compiling your library. This would be the one that gets installed, and consists of the necessary contents from the other headers. (I still don't think you would need everything from every header in your lib.)
I would discourage Salgar's solution. You either have individual headers, or a monolithic one. Providing individual headers plus a central one that simply includes the others strikes me as pretty poor layout.
What I do not understand is inhowfar Makefiles play into this. Header dependencies should be resolved automatically by your Makefile / build system, i.e. it shouldn't matter here how your header files are layed out.
Upvotes: 1