How do I pack a function from a static library into an .so file with fortran (MKL) - linux

I'm trying to speed up an optimization routine using MKL's blas implementation in fortran. I need to have the result in a shared library so that it is accessible from a larger script. I can compile and link my code without any warnings, but the resulting .so file has an undefined reference to the blas routine I'm trying to call, namely dgemm.
relevant section of the fortran code:
subroutine sumsquares(params, Mx, flen, glen, numr, numcols, g, lambda, res)
implicit none
integer, intent(in):: flen, glen, numr, numcols
real(8), dimension(flen, numcols) :: params
real(8), dimension(flen, numcols) :: g
real(8), dimension(flen, numcols) :: gc
real(8), dimension(flen, glen) :: Mx
gc = -g
call dgemm('N', 'N', flen, glen, numcols, 1, Mx, flen, params, numcols, 1, gc,flen)
return
end subroutine sumsquares
and the corresponding makefile
FC=ifort
LD_LIBRARY_PATH=/opt/intel/composerxe-2011.1.107/compiler/lib/intel64:/opt/intel/composerxe-2011.1.107/mkl/lib/intel64
LIBRARY_PATH=/opt/intel/composerxe-2011.1.107/compiler/lib/intel64:/opt/intel/composerxe-2011.1.107/mkl/lib/intel64
INCLUDE=/opt/intel/composerxe-2011.1.107/mkl/include
FPATH=/opt/intel/composerxe-2011.1.107/mkl/include
CPATH=/opt/intel/composerxe-2011.1.107/mkl/include
FFLAGS=-i8 -I$(MKLROOT)/include/intel64/ilp64 -I$(MKLROOT)/include
LDFLAGS= -shared -nofor-main -fPIC
LINKLIBS=-fPIC -shared -L$(MKLROOT)/lib/intel64 $(MKLROOT)/lib/intel64/libmkl_blas95_ilp64.a -lmkl_rt -lpthread -lm
sumsquares: sumsquares.f90
$(FC) $(FFLAGS) -c -fPIC /opt/intel/composerxe-2011.1.107/mkl/include/blas.f90 -o blas95.o
$(FC) $(FFLAGS) -nofor-main -c -fPIC sumsquares.f90
$(FC) $(LDFLAGS) sumsquares.o $(LINKLIBS) sumsquares.o
As I said, I can run make without any warnings, but when I run nm sumsquares.so | grep dgemm I see U dgemm_, and when I try to load the .so file, I crash with a segfault (while calling an unrelated subroutine, so I don't think it's related to this code). How do I get the linker to put in the relevant function into the so file?
Update
I am loading the so file in an R script by calling dyn.load in R as follows:
Variation 1:
dyn.load("/home/me/path/sumsquares.so")
Variation 2:
dyn.load("/opt/intel/composerxe-2011.1.107/mkl/lib/intel64/libmkl_rt.so")
dyn.load("/home/me/path/sumsquares.so")
Both variations lead to the same result, with a segfault.
Update # 2
I should point out that intel MKL static libaries are compiled with the -fPIC flag, at least according to the documentation. I clearly don't know what I'm doing, but from what I can tell, something like this should be possible.
As blas is used extensively in scientific computing, I am concerned about collisions with different versions. If I'm linking statically within my so file, and load that so file into a program that uses a different blas implementation, would that lead to a collision, or would my library play nice?

If the library is really static, you cannot put in a shared library. Shared object code is compiled in a different way, so that it can work independent of the position. Flags like -fPIC must be used that are not used for static libraries.
Either compile your BLAS with dgemm as a dynamic library and load it before you load your custom library (perhaps the R dyn.load will load the dependencies automatically, I do not know, you can try) or just include the code of DGEMM into your own library and compile everything together into one .so.
Do not forget you have to use the MKL Linking Advisor https://software.intel.com/content/www/us/en/develop/articles/intel-mkl-link-line-advisor.html Do NOT link with the ILP64 library, unless you know what you are doing and have a good reason to do so.
Also, although most of the MKL is shipped with static libraries built using -fPIC, the Fortran 95 interfaces to LAPACK and BLAS are not. The source files for the interfaces are included, so you need to compile them yourself with -fPIC if you want to use them. They are found at $MKLROOT/interfaces/blas95 and $MKLROOT/interfaces/lapack95.

How do I get the linker to put in the relevant function into the so file?
That's not how shared libraries work; you need to ship the so with your other files (and set the appropriate RPATH), or link to a static version of the library.
When you say:
when I try to load the .so file, I crash with a segfault
This sounds like you're trying to directly dlopen() or something similar; just let the dynamic (runtime) linker do its job.

Related

Clang linker finding some symbols but not others

In my .nim code, I'm using the header pragma to include symbols from /usr/local/include/node/node_api.h (which then includes /usr/local/include/node/js_native_api.h).
proc napi_create_function(
env: napi_env,
utf8name: cstring,
length: csize_t,
cb: napi_callback,
data: pointer,
res: napi_value
): int {.header:"<node/node_api.h>".}
When I run nim c foo.nim, I get Undefined symbols for architecture x86_64 for symbols in js_native_api.h (eg: napi_create_function), but the symbols in node_api.h are found by the linker. Remember that node_api.h includes js_native_api.h (as seen here).
Undefined symbols for architecture x86_64:
"_napi_create_function", referenced from:
_createFn__NEWhgHCwqbksHULYRnxXfA in #m..#s..#s..#s.nimble#spkgs#snapibindings-0.1.0#snapibindings.nim.c.o
The root problem likely isn't related to Nim, but I don't know how to use clang to check if the problem is reproducible without Nim.
So my question is:
How do I get the linker to find the missing symbols?
Versions
nim v1.4.8
clang v12.0.0
x86_64-apple-darwin19.6.0
nodejs v14.13.1 (installed with Homebrew into /usr/local/Cellar/node/14.13.1)
nim c
/Users/alec/.nimble/bin/nim
c
--colors:on
--noNimblePath
-d:NimblePkgVersion=0.1.0
--path:/Users/alec/.nimble/pkgs/nimdbx-0.4.1
--path:/Users/alec/.nimble/pkgs/nimterop-0.6.13
--path:/Users/alec/.nimble/pkgs/regex-0.19.0
--path:/Users/alec/.nimble/pkgs/unicodedb-0.9.0
--path:/Users/alec/.nimble/pkgs/cligen-1.5.4
--path:/Users/alec/.nimble/pkgs/cbor-0.6.0
--path:/Users/alec/.nimble/pkgs/napibindings-0.1.0
--path:'/Users/alec/.nimble/pkgs/docopt-#master'
--path:/Users/alec/.nimble/pkgs/regex-0.19.0
--path:/Users/alec/.nimble/pkgs/unicodedb-0.9.0
--hints:off
-o:/Users/alec/my-project/dist/foo
/Users/alec/my-project/foo.nim
clang
clang
-o
/Users/alec/my-project/foo
/Users/alec/.cache/nim/foo_d/stdlib_assertions.nim.c.o
/Users/alec/.cache/nim/foo_d/stdlib_dollars.nim.c.o
/Users/alec/.cache/nim/foo_d/stdlib_formatfloat.nim.c.o
/Users/alec/.cache/nim/foo_d/stdlib_io.nim.c.o
/Users/alec/.cache/nim/foo_d/stdlib_system.nim.c.o
/Users/alec/.cache/nim/foo_d/#m..#s..#s..#s.nimble#spkgs#snapibindings-0.1.0#snapibindings#sutils.nim.c.o
/Users/alec/.cache/nim/foo_d/#m..#s..#s..#s.nimble#spkgs#snapibindings-0.1.0#snapibindings.nim.c.o
/Users/alec/.cache/nim/foo_d/stdlib_parseutils.nim.c.o
/Users/alec/.cache/nim/foo_d/stdlib_math.nim.c.o
/Users/alec/.cache/nim/foo_d/stdlib_unicode.nim.c.o
/Users/alec/.cache/nim/foo_d/stdlib_strutils.nim.c.o
/Users/alec/.cache/nim/foo_d/stdlib_posix.nim.c.o
/Users/alec/.cache/nim/foo_d/stdlib_options.nim.c.o
/Users/alec/.cache/nim/foo_d/stdlib_times.nim.c.o
/Users/alec/.cache/nim/foo_d/stdlib_os.nim.c.o
/Users/alec/.cache/nim/foo_d/stdlib_hashes.nim.c.o
/Users/alec/.cache/nim/foo_d/stdlib_tables.nim.c.o
/Users/alec/.cache/nim/foo_d/#m..#s..#s..#s.nimble#spkgs#snimterop-0.6.13#snimterop#sglobals.nim.c.o
/Users/alec/.cache/nim/foo_d/stdlib_streams.nim.c.o
/Users/alec/.cache/nim/foo_d/stdlib_lexbase.nim.c.o
/Users/alec/.cache/nim/foo_d/stdlib_parsejson.nim.c.o
/Users/alec/.cache/nim/foo_d/stdlib_json.nim.c.o
/Users/alec/.cache/nim/foo_d/stdlib_cpuinfo.nim.c.o
/Users/alec/.cache/nim/foo_d/#m..#s..#s..#s.nimble#spkgs#snimdbx-0.4.1#snimdbx#sprivate#slibmdbx.nim.c.o
/Users/alec/.cache/nim/foo_d/#m..#s..#s..#s.nimble#spkgs#snimdbx-0.4.1#snimdbx#sprivate#svals.nim.c.o
/Users/alec/.cache/nim/foo_d/#m..#s..#s..#s.nimble#spkgs#snimdbx-0.4.1#snimdbx#sError.nim.c.o
/Users/alec/.cache/nim/foo_d/#m..#s..#s..#s.nimble#spkgs#snimdbx-0.4.1#snimdbx#sDatabase.nim.c.o
/Users/alec/.cache/nim/foo_d/#m..#s..#s..#s.nimble#spkgs#snimdbx-0.4.1#snimdbx#sData.nim.c.o
/Users/alec/.cache/nim/foo_d/#m..#s..#s..#s.nimble#spkgs#snimdbx-0.4.1#snimdbx#sCollection.nim.c.o
/Users/alec/.cache/nim/foo_d/#m..#s..#s..#s.nimble#spkgs#snimdbx-0.4.1#snimdbx#sTransaction.nim.c.o
/Users/alec/.cache/nim/foo_d/#m..#s..#s..#s.nimble#spkgs#snimdbx-0.4.1#snimdbx#sCRUD.nim.c.o
/Users/alec/.cache/nim/foo_d/#mfoopkg#sdata.nim.c.o
/Users/alec/.cache/nim/foo_d/#mfoopkg#sdata#sfrom_json.nim.c.o
/Users/alec/.cache/nim/foo_d/#mfoopkg#sdata#sto_json.nim.c.o
/Users/alec/.cache/nim/foo_d/#mfoopkg#squery.nim.c.o
/Users/alec/.cache/nim/foo_d/#m..#s..#s..#s.nimble#spkgs#scbor-0.6.0#scbor.nim.c.o
/Users/alec/.cache/nim/foo_d/#mfoopkg#sdata#sfrom_cbor.nim.c.o
/Users/alec/.cache/nim/foo_d/#mfoopkg#sdata#sto_cbor.nim.c.o
/Users/alec/.cache/nim/foo_d/#mfoopkg#sref.nim.c.o
/Users/alec/.cache/nim/foo_d/#mfoopkg#squery#sdocument.nim.c.o
/Users/alec/.cache/nim/foo_d/#mfoopkg#sfunctions.nim.c.o
/Users/alec/.cache/nim/foo_d/#mfoopkg#seval.nim.c.o
/Users/alec/.cache/nim/foo_d/#mfoo.nim.c.o
-lm
/Users/alec/.nimble/pkgs/nimdbx-0.4.1/libmdbx-dist/libmdbx.a
-ldl
So my question is:
How do I get the linker to find the missing symbols?
make sure you are actually linking a library (statically or dynamically) which holds symbols you need. (please show how you link it.)
make sure your library actually HAS correct symbols (open file with hex editor and search for symbols)
make sure this library is of correct architecture. there are tools that let you check this. (on Windows it's dumpbin /headers file)
make sure you are importing it correctly. (i see only {.header.} pragma but others needed pragmas are absent). please show more code and command lines. so we can investigate further.

When linking a shared library on linux, are all modules included?

I'm porting a system of apps from AIX to linux, and all of those apps include a single shared library. I've got the shared library building on as a linux .so now - and I see at least one post here that describes how to specify what's exported from a shared library (as AIX does via a .exp file).
Just one silly question, though. On AIX, if a module in a shared library is not referenced by anything in the app that's linking to it, it is ignored by the linker. That doesn't seem to be the case on linux - but I want to make sure.
While testing my linux shared library, I left out one module with dependencies I wasn't ready to deal with yet (or more accurately, I provided a substitute module with dummy functions for all the entry points to that module, thinking that would allow it to link). So far, so good. But when I attempted to link that shared library into a trivial test app, the linker reported unresolved symbols for stuff referenced by another shared library module that is itself only referenced from within the module I replaced with dummies. I.e., I would have expeceted that module to simply be ignored...
In other words, this module is being considered by the linker as part of the final application even though nothing in the app references it. I tried the same experiment on AIX (replacing the same module with dummies and attempting to link a trivial app there). No complaints.
So, The AIX linker only attempts to resolve shared library module dependencies if those modules themselves are explicitly called in from the application. But the linux linker attempts to resolve dependencies for all shared library modules whether they're called in from the application or not.
Is this true? And if so, is there any way to override that behavior? Ultimately, when I port everything, all of the dependencies will resolve. But for now, it's hard to leave something out - even if it's not referenced...
Here's a minimal case:
main.c contains function main(), which calls function one().
one.c contains function one(), which does nothing.
two.c contains function two(), which calls function three().
There is no function three(), but libshared.so is built from
modules one.c and two.c. Program main is built from main.c and
links in libshared.so.
The linker needs to resolve function one(), which is in the shared
library. But that's all main.c requires. Still, function two() in
the library references function three(), which doesn't exist.
The linker will complain about the undefined symbol 'three', even
though program main doesn't need it.
On AIX the linker will not complain and everything will work.
main.c:
#include <stdio.h>
int one();
int main()
{
one();
}
one.c:
#include <stdio.h>
int one()
{
return 1;
}
two.c:
#include <stdio.h>
int three();
int two()
{
return three();
}
build libshared.so with modules one.c and two.c:
gcc -fPIC -shared one.c two.c -o libshared.so
Attempt to build main from main.c and libshared.so:
gcc main.c -o main -L. -lshared
./libshared.so: undefined reference to `three'
collect2: error: ld returned 1 exit status
The linker reports an undefined reference to 'three',
which is referenced from two() - but main() doesn't ever call two().
The actual answer: shared libraries are in fact shared objects: they are treated as a single object, not as a *.a library.
This shows that Linux (meaning: glibc/gcc/gold/ld) and AIX have different concepts regarding shared objects.
In Linux, when you link an executable, ld/gold checks the dependencies of the used shared objects as well -- Aix linker doesn't: it assumes that the shared objects are to be used as they are, their dependencies aren't part of the current linking. (At least this is the default behaviour.)
Here is a summary of my tests:
+----------------+--------------------+-------------------------------+
| | AIX | linux |
+----------------+--------------------+-------------------------------+
| libshared.so | only with option | yes |
| can be created | -Wl,-berok | |
+----------------+--------------------+-------------------------------+
| main | yes | only with option |
| can be created | | -Wl,--allow-shlib-undefined |
+----------------+--------------------+-------------------------------+
Note: My random thoughts regarding AIX and linking: http://lzsiga.users.sourceforge.net/aix-linking.html
By default the GNU binutils linker, ld on
Linux requires a symbol ref to be defined by some input file (i.e. object file or
shared library) in the linkage if ref is referenced by the definition of any
symbol def in any input file that the linkage needs. It doesn't matter whether def is referenced in turn.
Your program linkage needs libshared.so. libshared.so defines two, which refers to three,
so three must be defined.
You can countermand this default behaviour to tolerate undefined references in shared libraries
(but not in object files) as follows:
$ gcc main.c -o main -L. -lshared -Wl,--allow-shlib-undefined
--allow-shlib-undefined is documented in the ld manual
The notion of module in your language corresponds to translation unit at the
compilation level and object file at the linkage level. It might be helpful to
appreciate that an object file input to the linkage of a ELF program or shared library
has no distinct existence in the program or shared library. It is cut into
pieces and scattered around. So there is no sense in which it would be possible
for a linkage:
$ gcc main.c -o main -L. -lshared ...
to ignore the unreferenced module two.(c|o) within
libshared.so. There is no such thing. If that linkage did not need any
definition provided by libshared.so then it would ignore the shared library
altogether1. If it needs the shared library, then by default its references
must be resolved.
[1] That is, on Debian-clan systems where gcc is built to invoke ld with the --as-needed option
by default. On Redhat-clan systems GCC by default links shared libraries if they are input, needed or not.

Can't find -lfftw when compiling a Fortran example

My aim is just to test FFTW on a one dimensional example. I've already installed everything, following the instructions. When I try to compile:
gfortran fftg.f90 -L/usr/local/lib -lfftw3
The terminal is giving the error:
/usr/bin/ld : can't find -lfftw3
I don't understand why because it is installed on my compute and when I'm searching for it, the library of FFTW is here
/usr/local/lib$ ls
cmake libfftw3.a libfftw3.la pkgconfig python2.7 python3.4 R site_ruby
I did not find any answer. Where the error is coming from? For more details, this is my code (taken from http://homepage.ntu.edu.tw/~wttsai/fortran)
program example
implicit none
include 'fftw3.f90'
integer, parameter :: N=16
integer*8 :: PLAN_FOR,PLAN_BAC
real*8,dimension(N) :: IN,OUT,IN2
real*8 :: xj
integer :: j,k,mode
real*8, parameter ::twopi=2.*acos(-1.)
!Discrete data of function f(x)=cos(x)+0.2*sin(2x)
do j=0,N-1
xj=twopi*real(j)/real(N)
IN(j)=cos(xj) +0.2*sin(2.*xj)
end do
write(*,*) "Original data"
do j=1,N
write(*,100) j,IN(j)
end do
100 format(i4,f12.5)
! Forward transform
call dfftw_plan_r2r_1d(PLAN_FOR,N,IN,OUT,FFTW_R2HC,FFTW_ESTIMATE)
call dfftw_execute_r2r(PLAN_FOR,IN,OUT)
OUT=OUT/real(N,KIND=8)
! Normalize
write(*,*) "Fourier coefficient after forward FFT"
do k=1,N
mode=k-1
if(k > N/2+1) mode=N-k+1
write(*,100) mode,OUT(k)
end do
call dfftw_destroy_plan(PLAN_FOR)
end program example
You normally have to setup the paths too, but I see you are using -L/usr/local/lib instead. That should suffice for the linking (not necessarily for running).
But your compiled FFTW is static (.a) and you are compiling dynamically. You can try compiling with -static. If you need to link dynamically you need to install also the dynamic version (.so) of the library (i.e. NOT use -enable-static in configure).

Accessing .so libraries using dlopen() throws undefined symbol error

I'm trying to dynamically load a camera library .so file into a Linux executable to gain access to simple camera functions.
I'm attempting to do this by:
if ( (newHandle = dlopen("./libCamera.so",RTLD_LAZY | RTLD_GLOBAL)) == NULL )
{
printf( "Could not open file : %s\n", dlerror() );
return 1;
}
However this fails and I receive the following output:
"Could not open file : libCamera.so: undefined symbol: ZTVN10_cxxabiv117__class_type_infoE"
How do I find out what symbols it is relying on?
Most likely, libCamera.so uses a symbol defined in a shared library without depending on that library.
Find a culprit. Take a real executable which links against libCamera.so (and it works). List its dependencies with ldd /path/to/executable. Among them should be a library which has a definition for ZTVN10_cxxabiv117__class_type_infoE (use grep to select likely candidates, nm -D on a library to be sure). That library won't be in the list shown by ldd ./libCamera.so.
Solve a problem. Load the library found in step 1 by dlopen first (use RTLD_GLOBAL there as well).
If there is a problem with another symbol, goto step 1.
If newly-added libraries have the same problem too, goto step 1.
Tell library authors to please fix their linking.
It could also happen that one of the prerequisites in ldd ./libCamera.so got upgraded and lost a symbol definition (maybe it was recompiled with a compiler which does name mangling differently). Then you won't find the culprit in step 1, and there is no solution but downgrading something again.
The ldd command can be used to display shared library dependencies.
ldd libCamera.so
Once you know the dependencies, you can use nm to show the symbols in each library.
nm -DC libCamera.so
I had a similar problem. It was to do with a .a library, which should have been linked to my .so and statically linked into the archive being left out.
I determined this with (OP object name used here):
nm mylibrary.so | grep ZTVN10_cxxabiv117__class_type_infoE
0000ABC0 U ZTVN10_cxxabiv117__class_type_infoE
The U here means that the symbol is "undefined". You can find the demangled name of the missing object with --demangle:
$ nm --demangle mylibrary.so | grep 0000ABC0
0000ABC0 U abi::class_type_info(params...)
(or something like that) this should help you figure out which library is missing.
In my case, even after including the library on the compiler line I still had the issue. Eventually, after some tinkering I discovered that the library-file (.a) has to come after its dependent object (.o) file like:
g++ -Wl,-E -g -m32 ... -fPIC myobjects1.o myobjects2.o missing_library.a -shared -o mylibrary.so
Now I get (no more U):
$ nm --demangle mylibrary.so | grep 0000ABC0
0000ABC0 T abi::class_type_info(params...)
and most importantly I don't get the error any more!
In your source code for libCamera.so, you have unresolved external symbol. It means that type_infoE have no definition in your source code and should be resolved.

Installing and Linking PhysX Libraries in Debian Linux

I am trying to get PhysX working using Ubuntu.
First, I downloaded the SDK here:
http://developer.download.nvidia.com/PhysX/2.8.1/PhysX_2.8.1_SDK_CoreLinux_deb.tar.gz
Next, I extracted the files and installed each package with:
dpkg -i filename.deb
This gives me the following files located in /usr/lib/PhysX/v2.8.1:
libNxCharacter.so
libNxCooking.so
libPhysXCore.so
libNxCharacter.so.1
libNxCooking.so.1
libPhysXCore.so.1
Next, I created symbolic links to /usr/lib:
sudo ln -s /usr/lib/PhysX/v2.8.1/libNxCharacter.so.1 /usr/lib/libNxCharacter.so.1
sudo ln -s /usr/lib/PhysX/v2.8.1/libNxCooking.so.1 /usr/lib/libNxCooking.so.1
sudo ln -s /usr/lib/PhysX/v2.8.1/libPhysXCore.so.1 /usr/lib/libPhysXCore.so.1
Now, using Eclipse, I have specified the following libraries (-l):
libNxCharacter.so.1
libNxCooking.so.1
libPhysXCore.so.1
And the following search paths just in case (-L):
/usr/lib/PhysX/v2.8.1
/usr/lib
Also, as Gerald Kaszuba suggested, I added the following include paths (-I):
/usr/lib/PhysX/v2.8.1
/usr/lib
Then, I attempted to compile the following code:
#include "NxPhysics.h"
NxPhysicsSDK* gPhysicsSDK = NULL;
NxScene* gScene = NULL;
NxVec3 gDefaultGravity(0,-9.8,0);
void InitNx()
{
gPhysicsSDK = NxCreatePhysicsSDK(NX_PHYSICS_SDK_VERSION);
if (!gPhysicsSDK)
{
std::cout<<"Error"<<std::endl;
return;
}
NxSceneDesc sceneDesc;
sceneDesc.gravity = gDefaultGravity;
gScene = gPhysicsSDK->createScene(sceneDesc);
}
int main(int arc, char** argv)
{
InitNx();
return 0;
}
The first error I get is:
NxPhysics.h: No such file or directory
Which tells me that the project is obviously not linking properly. Can anyone tell me what I have done wrong, or what else I need to do to get my project to compile? I am using the GCC C++ Compiler. Thanks in advance!
It looks like you're confusing header files with library files. NxPhysics.h is a source code header file. Header files are needed when compiling source code (not when linking). It's probably located in a place like /usr/include or /usr/include/PhysX/v2.8.1, or similar. Find the real location of this file and make sure you use the -I option to tell the compiler where it is, as Gerald Kaszuba suggests.
The libraries are needed when linking the compiled object files (and not when compiling). You'll need to deal with this later with the -L and -l options.
Note: depending on how you invoke gcc, you can have it do compiling and then linking with a single invocation, but behind the scenes it still does a compile step then a link step.
EDIT: Extra explanation added...
When building a binary using a C/C++ compiler, the compiler reads the source code (.c or .cpp files). While reading it, there are frequently #include statements that are used to read .h files. The #include statements give the names of files that must be loaded. Those exact files must exist in the include path. In your case, a file with the exact name "NxPhysics.h" must be found somewhere in the include path. Typically, /usr/include is in the path by default, and so is the current directory. If the headers are somewhere else such as a subdirectory of /usr/include, then you always need to explicitly tell the compiler where to look using the -I command-line switches (or sometimes with environment variables or other system configuration methods).
A .h header file typically includes data structure declarations, inline function definitions, function and class declarations, and #define macros. When the compilation is done, a .o object file is created. The compiler does not know about .so or .a libraries and cannot use them in any way, other than to embed a little bit of helper information for the linker. Note that the compiler also embeds some "header" information in the object files. I put "header" in quotes because the information only roughly corresponds to what may or may not be found in the .h files. It includes a binary representation of all exported declarations. No macros are found there. I believe that inline functions are omitted as well (though I could be wrong there).
Once all of the .o files exist, it is time for another program to take over: the linker. The linker knows nothing of source code files or .h header files. It only cares about binary libraries and object files. You give it a collection of libraries and object files. In their "headers" they list what things (data types, functions, etc.) they define and what things they need someone else to define. The linker then matches up requests for definitions from one module with actual definitions for other modules. It checks to make sure there aren't multiple conflicting definitions, and if building an executable, it makes sure that all requests for definitions are fulfilled.
There are some notable caveats to the above description. First, it is possible to call gcc once and get it to do both compiling and linking, e.g.
gcc hello.c -o hello
will first compile hello.c to memory or to a temporary file, then it will link against the standard libraries and write out the hello executable. Even though it's only one call to gcc, both steps are still being performed sequentially, as a convenience to you. I'll skip describing some of the details of dynamic libraries for now.
If you're a Java programmer, then some of the above might be a little confusing. I believe that .net works like Java, so the following discussion should apply to C# and the other .net languages. Java is syntactically a much simpler language than C and C++. It lacks macros and it lacks true templates (generics are a very weak form of templates). Because of this, Java skips the need for separate declaration (.h) and definition (.c) files. It is also able to embed all the relevant information in the object file (.class for Java). This makes it so that both the compiler and the linker can use the .class files directly.
The problem was indeed with my include paths. Here is the relevant command:
g++ -I/usr/include/PhysX/v2.8.1/SDKs/PhysXLoader/include -I/usr/include -I/usr/include/PhysX/v2.8.1/LowLevel/API/include -I/usr/include/PhysX/v2.8.1/LowLevel/hlcommon/include -I/usr/include/PhysX/v2.8.1/SDKs/Foundation/include -I/usr/include/PhysX/v2.8.1/SDKs/Cooking/include -I/usr/include/PhysX/v2.8.1/SDKs/NxCharacter/include -I/usr/include/PhysX/v2.8.1/SDKs/Physics/include -O0 -g3 -DNX_DISABLE_FLUIDS -DLINUX -Wall -c -fmessage-length=0 -MMD -MP -MF"main.d" -MT"main.d" -o"main.o" "../main.cpp"
Also, for the linker, only "PhysXLoader" was needed (same as Windows). Thus, I have:
g++ -o"PhysXSetupTest" ./main.o -lglut -lPhysXLoader
While installing I got the following error
*
dpkg: dependency problems prevent configuration of libphysx-dev-2.8.1:
libphysx-dev-2.8.1 depends on libphysx-2.8.1 (= 2.8.1-4); however:
Package libphysx-2.8.1 is not configured yet.
dpkg: error processing libphysx-dev-2.8.1 (--install):
dependency problems - leaving unconfigured
Errors were encountered while processing:
*
So I reinstalled *libphysx-2.8.1_4_i386.deb*
sudo dpkg -i libphysx-2.8.1_4_i386.deb

Resources