This is a really basic question, and I have found a lot of conceptual answers online, but failed to actually make it work.
Here is what I have:
file source.cc
#include <iostream>
int myfunc() {
return 42;
}
int main() {
return 0;
}
and then I create an object file source.o via:
g++ -c source.cc
finally, I use
ar rvs source.a source.o
to get the source.a static library.
Now, here comes trouble.
file user.cc looks like this:
#include <iostream>
#include <source.a>
int main() {
std::cout << myfunc();
}
where I evidently want to use the function defined in the library, but when trying to compile the user.cc:
g++ user.cc -o user
the error I get is:
user.cc:2:22: fatal error: source.a: No such file or directory
compilation terminated.
#include is compile time and must be C/C++ header (not library) containing e.g this
extern int myfunc();
than you have to use linker to compile it all togehter (specify all the files needed on the command line)
In addition to what others already wrote on the syntax to properly use g++ on the command line, you may want to consider the following notes on your code organization.
In your library code, you should not define the main() function. The definition of main() should instead be part of the code that uses your library, i.e the file user.cc in your example.
Moreover, you may want to distribute to the clients of the library a header file, that they can use to import the declarations of the functions exported by the library.
So, consider defining some files like this:
Header File:
// library.h -- Public header for your library's clients
#pragma once // or use #ifndef/#define/#endif "header guards"
// Functions exported by your library:
// their *declarations* go in the library's public header file;
// their *definitions* go in the library's implementation file(s) (.cc, .cpp)
// (exception: inline functions/methods, that are implemented in headers).
int myfunc();
// Add some other exported functions...
// NOTE: "extern" not needed in C++!
Implementation File:
// library.cc -- Library implementation code
#include "library.h" // library public header
#include <...> // headers required by this implementation code
// *Define* functions exported by the library
int myfunc() {
return 42;
}
// ...other function implementations...
Then, the library's client will just do:
File containing main() and using your library:
// main.cc (or user.cc or whatever you call it)
#include <iostream> // For std::cout, std::endl
...#include any other required header file...
#include "library.h" // Your library public header file
int main() {
// Call library's function
std::cout << myfunc() << std::endl;
}
// NOTE: main() is special: "return 0;" can be omitted.
Don't #include a library archive. It does not contain source code. It contains object code. Put it on the linker's command line.
Compile with g++ -c user.cc.
Link with g++ -o user user.o source.a.
In C++ (and C99), every function you call much be declared ahead of time. To do this you provide the "signature" of the function, without the the definition. In your case, this would be the statement
int myfunc();
which tells the compiler that myfunc is a function which takes no arguments and returns an int. Typically you would include this function declaration in a header.
A .a file is a compiled archive which does not contain C or C++ code, so #include-ing it into a C++ file will not work. Instead you need to create a C or C++ header, and add the .a archive to the list of files to be linked into the final executable. With g++, this is quite easy, you can say
g++ user.cc source.a -o executable
for example.
By default the #include <...> construct (with angle brackets) search system directories to find the specified files. To search other directories you can use the -L option, and to link with your library you need to use source.a in the command line. Like this:
g++ user.cc -L/path/to/library source.a -o user
A couple of ideas to add to the discussion
1) You should create a header file called source.h that contains the line
int myfunc();
or,
extern int myfunc();
2) In user.cc at the top should be a line
include "source.h"
This will tell the compiler the function is defined
3) I think you should take the main function out of source.cc, or at least make it static
As others have pointed out, you can't include a library file (source.a)
your compile and link process should work as is.
You can use headear files using #include. If you want to use libraries you have to tell the linker where to look for library files.
Check these articles for static and dynamic libraries:
Static and dynamic libraries
Using libraries in VS2005
Using libraries in Code::Blocks
Related
I don't have a problem that needs solving but was very puzzled by the following:
I'm using CMake (which uses gcc internally). Not sure if this is important.
Suppose I have a project consisting of a C++ static library LibCpp and a demo C++ executable DemoCpp, which links to and uses LibCpp. The library LibCpp is compiled from both C and C++ sources. The correct way to do this is for the C++ code files of LibCpp to inlucde all C headers as extern "C" {#include "c_header.h"}. If this is done, the static library links fine and the executable DemoCpp sucessfully links to LibCpp. Everything works.
Suppose, that I forgot to put in the extern "C"'s and just include the C headers as C++ headers. As expected, the full project fails to link. However, and this is what puzzles me, the linking fails when DemoCpp tries to link to LibCpp! I would have expected it to fail already at linking the static library. However, the static library (e.g. LibCpp.a file) are built just fine, it just cannot be used.
This is very puzzling to me, because to link the static library (I would think) the linker has to resolve the references into the code compiled as C. This is also annoying in my opinion, since I cannot rely on a library being "linkable to" only since the library itself managed to be linked. Am I missing something?
You do not need to look at below code examples, unless you don't understand my question or don't believe what I said.
# CMakeLists.txt
cmake_minimum_required(VERSION 3.17)
project(LibraryLinkerEvil)
# Toggle this line to see that linking fails for DemoCpp BUT NOT FOR LibCpp!!!
add_compile_definitions(USE_EXTERN_C)
set(CMAKE_CXX_STANDARD 17)
add_library(LibCpp cpp_lib.cpp util.c)
add_executable(DemoCpp main.cpp)
target_link_libraries(DemoCpp PRIVATE LibCpp)
// cpp_lib.cpp
#ifdef USE_EXTERN_C
extern "C" {
#endif
#include "util.h"
#ifdef USE_EXTERN_C
}
#endif
int call_c_function(int a, int b) {
return add(a,b);
}
// main.cpp
#include <iostream>
int call_c_function(int a, int b); // could be in a separate C++ header.
int main() {
std::cout << "Hello, World! " << call_c_function(2,2) << std::endl;
return 0;
}
// util.h (C header)
#ifndef LIBRARYLINKEREVIL_UTIL_H
#define LIBRARYLINKEREVIL_UTIL_H
int add(int a, int b);
#endif //LIBRARYLINKEREVIL_UTIL_H
// util.c (C source file)
int add(int a, int b) {
return a+b;
}
I would have expected it to fail already at linking the static library.
The static "library" is not linked. Its constituent object files are archived - bundled together in an object archive for convenience's sake. That's what the static "library" is. You can think of it as a bunch of object files packed in a "zip" file that the linker can then decode.
So, the only linking the object archive undergoes is when the target binary itself is linked (be it into a .dll/.so or executable).
The use of the object archive is equivalent to the use of the constituent object files: instead of passing the archive to the linker, you can pass all the object files it contained, with same results.
On Unix, the typical name for the tool that manages object archives is ar (archiver) - a very descriptive name indeed. In Unix tradition, the static "libraries" are called object archives. The term static "library" is a confusing misnomer and should be banned.
Usually ar is a much smaller program than the linker - often an order of magnitude smaller. The most rudimentary archiving is just a concatenation with a header added.
Not all references need to be resolved when creating a library. What if your library code has dependencies on another library? Those references aren't resolved when the library is created. They're resolved when you link the library to your executable, in which case you need to also link it with other libraries to provide those dependencies.
Library liba.a:
void from_b();
void from_a()
{
from_b();
}
Libary libb.a:
void from_b()
{
...
}
main.cpp:
void from_a();
int main()
{
from_a();
}
Compiling/linking:
g++ main.cpp -la -lb
Without -lb you'd get an undefined reference error here.
Because C++ supports function overloading, function names are "mangled" during the compilation process so that they have unique names in the object file. Using extern "C" prevents that mangling from happening.
If you leave out extern "C" when compiling, then call_c_function is expecting to call a C++ function with the name add, in particular the mangled name would be _Z3addii. Since add exists in a .c file it has the unmangled name instead of the mangled name, so now _Z3addii is considered an external function just like printf, and like all other external functions they are expected to be resolved at link time of the executable, not compile time, and not when the static library is created.
When you create a static library, you're not actually linking. You're just grouping several object files together into a larger archive. That way, when linking actually happens, you only need to link a single file instead of multiple.
I have created C++ static library using object files (which has many sub directories). After creating static library created a C file and a wrapper file (header file which I have under C++ directories). Now I'm trying to compile the C file by linking the C++ static library it gives error for the header file
error : no such a file or directory.
When I use -I option (-I C++ header files location) compiled successfully and able to run. But I would like to use the static library without including header files location i.e only adding static library itself C program should compile successfully.
Below is the source:
Edit:
I have the below files under libbasic folder:
testdemo.h
#ifndef TESTDEMO_H
#define TESTDEMO_H
#include<iostream>
#include<string>
using namespace std;
class testdemo
{
public:
testdemo();
void CallingTestDemo();
};
#endif // TESTDEMO_H
testdemo.cpp
#include "testdemo.h"
testdemo::testdemo()
{
}
void testdemo::CallingTestDemo()
{
`cout <<" CallingTestDemo!!!!!!\n";
}
testbasic.h
#ifndef LIBBASIC_H
#define LIBBASIC_H
#ifdef __cplusplus
#include<iostream>
#include<testdemo.h>
using namespace std;
class Libbasic
{
public:
Libbasic();
void Display();
void DisplayName(char* name);
};
#endif
#ifdef __cplusplus
extern "C" {
void displayfromC();
void displayfromCName(char* name);
}
libbasic.cpp
#include "libbasic.h"
void displayfromC()
{
Libbasic llb;
llb.Display();
}
void displayfromCName(char* name)
{
Libbasic lb;
lb.DisplayName(name);
}
Libbasic::Libbasic()
{
}
void Libbasic::Display()
{
cout <<" C called C++ API \n";
testdemo td;
td.CallingTestDemo();
}
#endif
#endif // LIBBASIC_H
I compiled the above program and created library libbasic.a
Now Im creating C API file outside the libbasic folder to call the above functions used in C++
testApi.c
#include<stdio.h>
#include <libbasic.h>
int main()
{
displayfromC();
}
Now im trying to create output using the below
gcc -o testdemo testApi.c -L ./libbasic -lbasic
Which giving libbasic.h: no such a file or directory error.
The basic Idea is create a library and API functions which can be used in any machine. If I have multiple folders and header files in C++ code then need to include all the folders while creating C application which requires to export header files too. I dont want to expose all the source to other users.
Kindly let me what mistake im doing and also how to achieve this.
A header file is not a wrapper.
If you have functions in a library, whether static or dynamic, you must have their declarations (often called "prototypes") in your code.
That is how C and C++ work so header files are integral part of any library.
As for the location of header files, these languages give you three options:
Use <filename.h> for standard include header path.
This path depends on your OS and compiler, but as long as your header file is there, you will not need to specify the path explicitly in compilation command.
Use "filename.h" for files in your local source directory, i.e. same directory where your *.c or *.cpp files reside.
The compiler can look there automatically as well, but if the header is in a sub directory, you will need to specify the relative path in your include statement.
#include "mylib/myheader.h"
Add additional search path for header files using a parameter (such as -I for gcc).
Finally, similar rule applies to the library object file it self (*.a, *.lib).
You will need the -L parameter in addition to the -l parameter if your library is not in a standard library path known to the linker.
Note that you never specified which compiler you are using, so I am guessing based on parameter names it is from gcc family or similar.
A way to alter the search path and tell the compiler where to find your library files will differ based on compiler type, but the principle is the same.
I am a C++ learner and I came across a concept of separating code into multiple files to speed up compiling process on bigger projects.
However what the book doesn't tell me and I have tried to find it in other books and on the web, but with no luck is how does linker (during compilation) knows what files to include.
When I make new file I connect its header to the main file with #include "newfile.h", however in this header I don't write where to find definitions of functions.
So how I imagine the process is that it starts in the main file and there it finds "connections" to other files. The question is how it finds those .cpp files that as far as I see don't need to be named the same as its header file.
Exmple:
Main file:
#include <iostream>
#include "krneki_H.h"
using namespace std;
int main()
{
krneki1();
krneki2();
krneki3();
}
And header file:
void krneki1();
void krneki2();
void krneki3();
And new .cpp file:
#include <iostream>
#include "krneki_H.h"
using namespace std;
void krneki1() {
cout<<"Krneki1"<<endl;}
void krneki2() {
cout<<"Krneki2"<<endl;}
void krneki3() {
cout<<"Krneki3"<<endl;}
Notice that there is no indication to use second cpp file. It just knows to use it. Does it search all .cpp files in the map?
Thank you for answer.
You compile both .cpp files using gcc -c or a similar command line, and then pass both of the .o files produced to the linker. The linker does not magically figure out that you want to compile another .cpp file.
For example
gcc -c main.cpp -o main.o # compile
gcc -c krneki_H.cpp -o krneki_H.o # compile
gcc main.o krneki_H.o -o main # link
Your IDE may take care of these details automatically, in which case it compiles all .cpp files you added to your project, then links all the .o files produced by the compilation step.
No. It doesn't just know to use it. In your example, if you compile with main.cpp and without that new cpp file, you'll get an "undefined reference" error.
What happens is that you're using a fancy IDE that automatically compiles all cpp files. It includes them all by default in your makefile.
I recommend that you try to design a makefile from scratch, and see for yourself how you'll get that "undefined reference" error if you don't include the cpp file that has the implementations of your functions.
I have this simple code in C++
#include <something.h>
#include <something2.h>
int main()
{
my_function();
return 0;
}
function with name my_function is defined in something.h and also in something2.h How to choose whichone I want to use without editting included files?
One solution is to use
namespace something_one
{
#include <something.h>
}
namespace something_two
{
#include <something2.h>
}
This works well if all the code is in the headers.
Otherwise you have to resort to #defines, stub functions implemented in carefully crafted compilation units, or a robust conversation with the global namespace polluter.
Assuming that actual definition resides in something.cpp (or .c) and something2.cpp (or .c),
Link only one of something.o or something2.o at the time of creating main application executable, depending upon from which file you want function to get executed.
With linking the correct file, you do not need to change any source code.
you might have to declare them as extern "C" at the point declaration and definition if you are compiling it as c++ files with g++ or gcc -std=c++0x or gcc -std=c++11.
I am learning (trying) how to write my own C/C++ headers, and get functions out of the body of my code. For this I wrote nyanlib.h, and nyan.cpp
Ignoring that its a trivial program, please tell me if the header is written correctly, or if I am making serious mistakes? The code works though.
Here is nyan.cpp:
#include <iostream>
#include <unistd.h>
#include "nyanlib.h"
using namespace std;
int main()
{
while( true )
{
print_nyan(); //function from nyanlib
sleep(1);
}
return 0;
}
and Here is nyanlib.h
Also, Would nyanlib.h be a shared library or a static library?
What you have as nyanlib.h should be renamed to nyanlib.cpp. Then nyanlib.h would contain only the following:
#ifndef NYANLIB_H
#define NYANLIB_H
void print_nyan();
#endif
You can then compile the library as an object file:
g++ -c nyanlib.cpp
This gives you nyanlib.o. So now your main file contains just a prototype of print_nyan() from the header file so it knows how to call it.
Then you compile the main program:
g++ -c nyan.cpp
g++ -o nyan nyan.o nyanlib.o
Yes and no. While it is a valid header, you are using it a bit strangely. Most of the time, a header is used as a way to expose methods and variables related to the class and not to perform functionality.
For your case if you want to make it "better", I would bring the implementation of the print_nyan() function into the cpp file, and just leave a prototype of the function in the header.
And I would say that it is neither a static nor a shared library since it has a main. If you wanted to make it a library, you should make a separate header and source file that defines the print_nyan() function, make that your library, and use that library in your main function.