Problem compiling C-Function to Postgres; compiler didn't find postgres.h - c

I was asked to create a C-Function to integrate with Postgres. The Postgres documentation to this kind of function is available here: Postgres documentation.
The function I am trying to compile is from the manual and it is called add_one, just for test. But I had a problem while compiling it. The command I followed of the documentation was:
cc -fPIC -c foo.c
cc -shared -o foo.so foo.o
And the problem it returned was:
[igoralberte#localhost inside-postgres]$ cc -fPIC -c serializacao.c
serializacao.c:1:10: fatal error: postgres.h: Arquivo ou diretório inexistente
#include "postgres.h"
^~~~~~~~~~~~
compilation terminated.
In English, it means: Non-existent file or directory (postgres.h).
I have tried to copy some files I thought were important to /usr/lib directory. They were on /usr/include/pgsql or on /lib64. Those files were:
libpq.so
libpq.so.5
libpq.so.5.13
libpq (directory)
postgres_ext.h
Some important informations about my system:
I am using CentOS 8
System architecture: x86-64
GCC version: gcc (GCC) 8.4.1 20200928 (Red Hat 8.4.1-1)
Postgres version: 13.3
Thanks in advance!

It is a bold step to write a postgres plugin before you have a solid grasp on linux/unix, shell programming and how to compile c programs.
Typically your c compiler has to be told where to find header files using the -I compiler switch. So if postgres.h is in /path/containing/headerfile, you must add -I/path/containing/headerfile to the compile command:
cc -I/path/containing/headerfile -fPIC -c foo.c
The postgres documentation you linked to tells you to use pg_config --includedir-server to find out where the the header files are stored.
I am not familiar with pg_config, but if it acts like similar tools and
gives the output -I/path/containing/headerfile when calling it with the paramater --includedir-server, then you don't have to hardcode the path in your compile command. But just write:
cc `pg_config --includedir-server` -fPIC -c foo.c
See "Command Substitution" in your favorite shell documentation.
I also recommend learning how to use a build-tool like make. Things are soon going to be tedious if you have to retype compilation and link commands all the time.
Oh, and by the way, you probably want to write #include <postgres.h> and not #include "postgres.h" (Unless you are a postgres contributor and postgres.h is part of your project files)

Related

C compiler not finding gmp linked library

I'm trying to compile a simple C program on an M1 Mac that includes gmp.h. For whatever reason, however, it continuously says that it can't find the library. I checked to see if it exists via locate libgmp.a to which it says it is located in /opt/local/lib/libgmp.a. I also attempted to install it via brew to no avail. I really don't understand what I'm doing wrong here. I also checked the PATH environment variable to make sure this path was included, which it is.
The output of find /opt/local -type f -name "gmp.h" is /opt/local/include/gmp.h, and the output of find /opt/local -type f -name "libgmp*" is
/opt/local/libgmp.a
/opt/local/lib/libgmpxx.4.dylib
/opt/local/lib/libgmp.a
/opt/local/lib/libgmpxx.a
/opt/local/lib/libgmp.10.dylib
I compiled by linking via -L/opt/local/lib -lgmp does not fix the issue.
Command used: gcc main.c -o main.o -L/opt/local/lib -lgmp
To compile a program that relies on a header file:
#include <gmp.h>
located in a non-standard location /usr/local/include/gmp.h you need to tell the compiler where to find it by setting the directory where to find the header file:
gcc -c main.c -I/usr/local/include
Note: gpp -x c -v
To link the program, you need to tell the compiler which library to use (-l) and where to find that library (-L) which in this case /usr/local/lib/gmp.a:
gcc main.o -o main -L/usr/local/lib -lgmp
Note: gcc -print-search-dirs | grep ^libraries
If you are using a dynamic library (.so), you may also need to tell the linker where to find the library at run-time:
export LD_LIBRARY_PATH=/usr/local/lib
./main

libtiff build undefined reference to `_imp__TIFFOpen' error

probably this is a trivial newbie question, however, I can't figure out how to solve it.
I'm trying to build a test program using libtiff (test program copied from here). I've downloaded the static library libtiff.lib as well as the required header file tiffio.h. When I compile the main c function with no problem I have a main.o file. When I try to link main.o with libtiff using this command
gcc -g -Wall -o test.exe ./libtiff.lib ./test.o
I have this error:
undefined reference to `_imp__TIFFOpen'
I've looked into the lib file with nm -A libtiff.lib command and I can find this line
libtiff.lib:libtiff3.dll:00000000 I __imp__TIFFOpen
but it has 2 leading underscores instead of 1 as required by the linker. I'm using mingw on Windows 7 and all the required files are in the same directory.
No clue how to link with no errors.
Thanks in advance.
As suggested in the the comments, it was sufficient to invert the order of objects passed as arguments:
gcc -g -Wall -o test.exe ./test.o ./libtiff.lib

a linker issue when learning static library [duplicate]

When I try to build the following program:
#include <stdio.h>
int main(void)
{
printf("hello world\n");
return 0;
}
On OS X 10.6.4, with the following flags:
gcc -static -o blah blah.c
It returns this:
ld: library not found for -lcrt0.o
collect2: ld returned 1 exit status
Has anyone else encountered this, or is it something that noone else has been affected with yet? Any fixes?
Thanks
This won’t work. From the man page for gcc:
This option will not work on Mac OS X unless all libraries (including libgcc.a) have also been compiled with -static. Since neither a static version of libSystem.dylib nor crt0.o are provided, this option is not useful to most people.
Per Nate's answer, a completely static application is apparently not possible - see also man ld:
-static Produces a mach-o file that does not use the dyld. Only used building the kernel.
The problem in linking with static libraries is that, if both a static and a dynamic version of a library are found in the same directory, the dynamic version will be taken in preference. Three ways of avoiding this are:
Do not attempt to find them via the -L and -l options; instead, specify the full paths, to the libraries you want to use, on the compiler or linker command line.
$ g++ -Wall -Werror -o hi /usr/local/lib/libboost_unit_test_framework.a hi.cpp
Create a separate directory, containing symbolic links to the static libraries, use the -L option to have this directory searched first, and use the -l option to specify the libraries you want to use.
$ g++ -Wall -Werror -L ./staticBoostLib -l boost_unit_test_framework -o hi hi.cpp
Instead of creating a link of the same name in a different directory, create a link of a different name in the same directory, and specify that name in a -l argument.
$ g++ -Wall -Werror -l boost_unit_test_framework_static -o hi hi.cpp
You may also try LLVM LLD linker - I did prebuilt version for my two major OSes - https://github.com/VerKnowSys/Sofin-llds
This one allows me to link for exmple: "Qemu" properly - which is impossible with ld preinstalled by Apple.
And last one is - to build GCC yourself with libstdc++ (don't).

Including headers file using GCC

Sorry. I think this question would be very easy to you guys.
I have two c files and one h file, I put those two .c files stack.c and main.c and one .h file stack.h inside a folder named "test" at Desktop.
So they are in C:\Users\user\Desktop\test
However when i try to test this code by writing
gcc -c stack.c sq_main.c -l stack.h
It continuously shows "unkown type name ..."
I think the header file is not included into those two .c files.
Actually I wrote the code
#include "stack.h"
Inside stack.c and main.c
Can anyone tell me how to include header file properly?
You are using GCC wrongly. I guess you are on Linux (or on something emulating it like MinGW ...)
If you insist on giving several commands in a terminal, you'll need to run
gcc -Wall -Wextra -g -c stack.c
gcc -Wall -Wextra -g -c sq_main.c
these two commands are building object files stack.o & sq_main.o (from stack.c & the #include-d stack.h, and sq_main.c & the #include-d stack.h, respectively). The options -Wall -Wextra are asking for all warnings and some extra warnings. The -g option asks for debugging information. The -c option asks for compiling only. Assuming that they are enough for your program, you need to link these object files to make an executable:
gcc -g stack.o sq_main.o -o myprogram
You might need to add -Iinclude-directory options to the compiling commands (the first two), and you might need to add -Llibrary-directory and -llibrary-name to the linking command. Order of arguments to gcc matters a lot. You could also add -H to ask the compiler to show which files are included. And GCC has a lot of other options. Read the Invoking GCC chapter of its documentation.
The .o suffix might be .obj on most Windows systems. You might also need myprogram.exe instead of myprogram. I never used Windows so I cannot help more.
In practice, you should use GNU make and write some Makefile; this answer might inspire you.

Include an external library in C

I'm attempting to use a C library for an opencourseware course from Harvard. The instructor's instructions for setting up the external lib can be found here.
I am following the instructions specific to ubuntu as I am trying to use this lib on my ubuntu box. I followed the instructions on the page to set it up, but when I run a simple helloWorld.c program using a cs50 library function, gcc doesn't want to play along.
Example:
helloWorld.c
#include <stdio.h>
#include <cs50.h>
int
main(void){
printf("What do you want to say to the world?\n");
string message = GetString();
printf("%s!\n\n", message);
}
$ gcc helloWorld.c
/tmp/ccYilBgA.o: In function `main':
helloWorld.c:(.text+0x16): undefined reference to `GetString'
collect2: ld returned 1 exit status
I followed the instructions to the letter as stated in the instructions, but they didn't work for me. I'm runing ubuntu 12.04. Please let me know if I can clarify further my problem.
First, as a beginner, you should always ask GCC to compile with all warnings and debugging information enabled, i.e. gcc -Wall -g. But at some time read How to invoke gcc. Use a good source code editor (such as GNU emacs or vim or gedit, etc...) to edit your C source code, but be able to compile your program on the command line (so don't always use a sophisticated IDE hiding important compilation details from you).
Then you are probably missing some Harvard specific library, some options like -L followed by a library directory, then -l glued to the library name. So you might need gcc -Wall -g -lcs50 (replace cs50 by the appropriate name) and you might need some -Lsome-dir
Notice that the order of program arguments to gcc is significant. As a general rule, if a depends upon b you should put a before b; more specifically I suggest
Start with the gcc program name; add the C standard level eg -std=c99 if wanted
Put compiler warning, debugging (or optimizing) options, eg -Wall -g (you may even want to add -Wextra to get even more warnings).
Put the preprocessor's defines and include directory e.g. -DONE=1 and -Imy-include-dir/
Put your C source file hello.c
Put any object files with which you are linking i.e. bar.o
Put the library directories -Lmy-lib-dir/ if relevant
Pur the library names -laa and -lbb (when the libaa.so depends upon libbb.so, in that order)
End with -o your-program-name to give the name of the produced binary. Don't use the default name a.out
Directory giving options -I (for preprocessor includes) and -L for libraries can be given several times, order is significant (search order).
Very quickly you'll want to use build automation tools like GNU make (perhaps with the help of remake on Linux)
Learn also to use the debugger gdb.
Get the habit to always ask for warnings from the compiler, and always improve your program till you get no warnings: the compiler is your friend, it is helping you!
Read also How to debug small programs and the famous SICP (which teaches very important concepts; you might want to use guile on Linux while reading it, see http://norvig.com/21-days.html for more). Be also aware of tools like valgrind
Have fun.
I take this course and sometimes I need to practice offline while I am traveling or commuting. Under Windows using MinGW and Notepad++ as an IDE (because I love it and use it usually while codding python) I finally found a solution and some time to write it down.
Starting from scratch. Steps for setting up gcc C compiler, if already set please skip to 5
Download Git and install. It includes Git Bash, which is MINGW64 linux terminal. I prefer to use Git as I need linux tools such as sed, awk, pull, push on my Windows and can replace Guthub's terminal.
Once Git installed make sure that gcc packages are installed. You can use my configuration for reference...
Make sure your compiler works. Throw it this simple code,
by saving it in your working directory Documents/Harvard_CS50/Week2/
hello.c
#include <stdio.h>
int main(void)
{
printf("Hello StackOverflow\n");
}
start Git Bash -> navigate to working directory
cd Documents/Harvard_CS50/Week2/
compile it in bash terminal
gcc helloworld.c -o helloworld.exe
execute it using bash terminal
./helloworld.exe
Hello StackOverflow
If you see Hello StackOverflow, your compiler works and you can write C code.
Now to the important bit, installing CS50 library locally and using it offline. This should be applicable for any other libraries introduced later in the course.
Download latest source code file cs50.c and header file cs50.h from https://github.com/cs50/libcs50/tree/develop/src and save them in Documents/Harvard_CS50/src
Navigate into src directory and list the files to make sure you are on the right location using
ls
cs50.c cs50.h
Cool, we are here. Now we need to compile object file for the library using
gcc -c -ggdb -std=c99 cs50.c -o cs50.o
Now using the generated cs50.o object file we can create our cs50 library archive file.
ar rcs libcs50.a cs50.o
After all this steps we ended with 2 additional files to our original files. We are interested in only 2 of them cs50.h libcs50.a
ls
cs50.c cs50.h cs50.o libcs50.a
Copy Library and header files to their target locations. My MinGW is installed in C:\ so I copy them there
cs50.h --> C:\MinGW\include
libcs50.a --> C:\MinGW\lib
Testing the cs50 Library
To make sure our library works, we can throw one of the example scripts in the lecture and see if we can compile it using cs50.h header file for the get_string() method.
#include <stdio.h>
#include <cs50.h>
int main(void)
{
printf("Please input a string to count how long it is: ");
string s = get_string();
int n = 0;
while (s[n] != '\0')
{
n++;
}
printf("Your string is %i chars long\n", n);
}
Compile cs50 code using gcc and cs50 library. I want to be explicit and use:
gcc -ggdb -std=c99 -Wall -Werror test.c -lcs50 -o test.exe
But you can simply point the source, output filename and cs50 library
gcc test.c -o test.exe -lcs50
Here we go, program is compiled using header and methods can be used within.
If you want Notepad++ as an IDE you can follow this tip to set it up with gcc as a compiler and run your code from there.
Just make sure your nppexec script includes the cs50 library
npp_save
gcc -ggdb -std=c99 -Wall -Werror "$(FULL_CURRENT_PATH)" -lcs50 -o "$(CURRENT_DIRECTORY)\$(NAME_PART).exe"
cmd /c "$(CURRENT_DIRECTORY)\$(NAME_PART).exe"
Download the cs50 from: http://mirror.cs50.net/library50/c/library50-c-5.zip
Extract it. (You will get two files cs50.c and cs50.h)
Now copy both the files to your default library folder. (which includes your stdio.h file)
Now while writing your program use: #include < cs50.c >
You can also copy the files to the folder containing your helloWorld.c file.
You have to use: #include " cs50.c ".
OR =====================================================================>
Open cs50.c and cs50.h files in text editor.
In cs50.h, just below #include < stdlib.h > add #include < stdio.h > and #include < string.h > both on new line.
Now open cs50.c file, copy everything (from: /**Reads a line of text from standard input and returns the equivalent {from line 47 to last}) and paste it in cs50.h just above the #endif and save the files.
Now you can copy the file cs50.h to either your default library folder or to your current working folder.
If you copied the file to default folder then use: #include < cs50.h > and if you copied the files to current working folder then use: #include " cs50.h ".
You need to link against the library during compilation. The library should end in .a or .so if you are on Ubuntu. To link against a library:
gcc -o myProgram myProgram.c -l(library name goes here but no parentheses)
You have to link against the library, how come GCC would know what library you want to use?
gcc helloWorld.c -lcs50
Research Sources:
building on the answers above given by Basile Starynkevitch, and Gunay Anach
combined with instructions from some videos on youtube 1 2
Approach:
covering the minimum things to do, and sharing the "norms" separately
avoiding any modification to anywhere else on the system
including the basic breakdown of the commands used
not including all the fine details, covering only the requirements absolute to task or for effective communication of instructions. leaving the other mundane details to the reader
assuming that the other stuff like compiler, environment variable etc is already setup, and familiarity with shell's file navigation commands is there
My Environment:
compiler: gcc via msys2
shell: bash via msys2
IDE: doesnt matter here
Plan:
getting the source files
building the required files: *.o (object) and *.a (archive)
telling the compiler to use it
Action:
Let's say, current directory = "desktop/cs50"
It contains all the *.c files like test-file.c which I will be creating for assignments/problem sets/practise etc.
Get the *.h and *.c files
Source in this particular case: https://github.com/cs50/libcs50/tree/main/src
Go over each file individually
Copy all the content of it
Say using "Copy raw contents" icon of individual files
Create the corresponding file locally in the computer
Do it in a a separate folder just to keep things clean, let's say in "desktop/cs50/src" aka ./src
Build the required files using in the terminal after changing your current directory to "desktop/cs50/src" :
gcc -c cs50.c to create the "cs50.o" object file from "cs50.c" using "gcc"
ar cr libcs50.a cs50.o to create "libcs50.a" archive file which'll be containing "cs50.o" object file
Here, "libcs50" = "lib" prefix + "cs50" name (same as the header file's name)
This is the norm/standard way where the prefix "lib" is significant as well for a later step
However, prefix can be skipped, and it's not compulsory for name to match the header file's name either. Though, Skipping prefix is not recommended. And I can't say for sure about the name part
To tell the compiler to be able to use this infrastructure, the commands will be in following syntax after going to the parent directory (i.e. to "desktop/cs50"):
gcc test-file.c -Isrc -Lsrc -lcs50 if you used "lib" prefix in step 2.2 above
here, -I flag is for specifying the directory of *.h header file included in your test_file.c
and -L flag is for specifying the directory to be used for -l
and -l is for the name of the *.a file. Here the "lib" prefix talked about earlier, and ".a" extension is not mentioned
the order of these flags matter, keep the -I -L -l flags after the "test-file.c"
Some more notees:
don't forget to use the additional common flags (like those suggested above for errors etc)
if you skipped the "lib" prefix, then you can't use -L -l flags
so, syntax for command will become: gcc test-file.c -Isrc src/libcs50.a
say i created my test-file.c file in "desktop/cs50/psets", so, it can be handled in 2 notable ways (current dir = "desktop/cs50/") :
cd psets then changing the relative address correspondingly in -I -L, so result:
gcc test-file.c -I../src -L../src -lcs50
keeping current directory same, but then changing the file's relative address correspondingly, so result:
gcc psests/test-file.c -Isrc -Lsrc -lcs50
or use absolute addresses 😜
as it can be seen that this becomes quite long, that's when build automation tools such as make kick in (though i am accomplishing that using a shell script 😜)

Resources