Why does CMake not respect LIBRARY_PATH and CPATH - linux

I'm using CMake on a HPC system that uses modules. Those modules usually set LIBRARY_PATH and CPATH so one can simply include headers and link against libraries without additional -L or -I.
However when using CMake those libraries must be found by CMake. I would expect, that LIBRARY_PATH and CPATH were automatically considered by CMake and captured in e.g. CMAKE_SYSTEM_LIBRARY_PATH and CMAKE_SYSTEM_INCLUDE_PATH but they are not.
Is there any reasoning why this was (not) done?
Wouldn't it be a good idea (for now manually, later automatically by CMake) to append LIBRARY_PATH to CMAKE_SYSTEM_LIBRARY_PATH and CPATH to CMAKE_SYSTEM_INCLUDE_PATH?

Is there any reasoning why this was (not) done?
Wouldn't it be a good idea (for now manually, later automatically by CMake) to append LIBRARY_PATH to CMAKE_SYSTEM_LIBRARY_PATH and CPATH to CMAKE_SYSTEM_INCLUDE_PATH?
There is another view that having your build depend on environment variables results in unreliable builds. From GNU Make manual:
It is not wise for makefiles to depend for their functioning on environment variables set up outside their control, since this would cause different users to get different results from the same makefile. This is against the whole purpose of most makefiles.

Related

autoconf: `PKG_CONFIG_PATH` not working in `configure.ac` when using `PKG_CHECK_EXISTS`

I want to check whether gmodule exists in my custom PKG_CONFIG_PATH
// configure.ac
AC_SUBST([PKG_CONFIG_PATH],"./glib/lib/x86_64-linux-gnu/pkgconfig/")
PKG_PROG_PKG_CONFIG
PKG_CHECK_EXISTS([gmodule-2.0],[],[
AC_MSG_ERROR(can't find gmodule in glib-2.0)
])
But I have the following error:
checking for libunwind.h... yes
checking for pkg-config... /usr/bin/pkg-config
checking pkg-config is at least version 0.9.0... yes
configure: error: can't find gmodule in glib-2.0
I'm 100 percent sure that gmodule-2.0.pc is in my custom path:
> ls ./glib/lib/x86_64-linux-gnu/pkgconfig/
gio-2.0.pc gio-unix-2.0.pc glib-2.0.pc gmodule-2.0.pc gmodule-export-2.0.pc gmodule-no-export-2.0.pc gobject-2.0.pc gthread-2.0.pc
And I can also use pkg-config to find gmodule-2.0:
> PKG_CONFIG_PATH="./glib/lib/x86_64-linux-gnu/pkgconfig/" pkg-config gmodule-2.0 --cflags
-pthread -I/home/xxx/fuzz/test/StochFuzz/glib/include -I/home/xxx/fuzz/test/StochFuzz/glib/include/glib-2.0 -I/home/xxx/fuzz/test/StochFuzz/glib/lib/x86_64-linux-gnu/glib-2.0/include
Do I miss something?
Do I miss something?
It looks like you are expecting this ...
AC_SUBST([PKG_CONFIG_PATH],"./glib/lib/x86_64-linux-gnu/pkgconfig/")
... to cause configure to use ./glib/lib/x86_64-linux-gnu/pkgconfig/ as the PKG_CONFIG_PATH when it runs pkg-config. In that case, you are at least missing that
the purpose of AC_SUBST() is to create an output variable. You want an output variable if you want to convey the pkg-config path to your Makefiles, but that is not directly relevant to your configure script.
although AC_SUBST does set the value of the specified shell variable if you designate a value for it,
It does not necessarily export that variable.
The assignment does not necessarily appear in the configure script at a place corresponding to the macro's location in configure.ac.
if you are trying to use components that are bundled with your project (and surely that's what you are doing if the wanted details are provided by pkg-config data from within your own source tree) then pkg-config is way overkill. Just put the needed paths and flags in your Makefile.am file(s), or if you're not using Automake then directly in your Makefile.in file(s).
If you insist on doing it with pkg-config anyway, then this variation will likely induce the behavior you want from the PKG_CHECK_EXISTS macro:
# configure.ac
PKG_CONFIG_PATH=./glib/lib/x86_64-linux-gnu/pkgconfig/
export PKG_CONFIG_PATH
PKG_PROG_PKG_CONFIG
PKG_CHECK_EXISTS([gmodule-2.0],[],[
AC_MSG_ERROR(can't find gmodule in glib-2.0)
])
If you also need to convey your custom PKG_CONFIG_PATH to your makefiles then you can add ...
AC_SUBST([PKG_CONFIG_PATH])
... but you shouldn't. Notwithstanding the fact that you shouldn't be using pkg-config at all in this case (see above), when you do use pkg-config in an Autotools build system, the best way to use it is entirely within configure. Extract the needed paths and flags there, and convey those to your makefiles via output variables.

How to set libs order in qmake?

We have a problem building out C++ software on Ubuntu Linux with qmake.
Problem is: we use some library, for example OpenCV, that can have different versions in one system.
qmake automatically add -L/usr/lib or -L/usr/lib/x86_64-linux-gnu to g++ arguments, and contents of LIBS variables after it.
So there conflicts with different versions of OpenCV, the system version is used, but we need custom one, located at our build tree.
Are there any methods to change libs order in -L or something else to solve this problem?
There are two components to doing this:
First, you need to make sure to include them in your .pro file correctly. Do this with something like (this is from my current project):
LIBS += L${OPENCV_HOME}/lib \
-lopencv_core \
-lopencv_highgui \
You can replace the environment variable with whatever your path is. I've found it convenient to use environment variables like this because you also need header includes:
INCLUDEPATH += $$(OPENCV_HOME)/include/opencv2 \
$$(OPENCV_HOME)/include/opencv \
$$(OPENCV_HOME)/include
This allows you to create projects and build them correctly.
When you attempt to run them, however, you will likely run into all sorts of issues due to your app finding the wrong libraries (from system libraries like you say) - you need to set your LD_LIBRARY_PATH variable correctly. In this case I have a launch script (you can do this in your user profile or elsewhere) which contains:
export LD_LIBRARY_PATH=${OPENCV_HOME}/lib
Which then looks to that (as well as other) locations on the LD_LIBRARY_PATH first, before system libraries.
Another hack is to exploit the LIBS = $(SUBLIBS) ... part of the Makefile qmake writes.
Namely, invoke the generated Makefile with
make SUBLIBS=-L/path/to/your/opencv
I had the same issue which I fixed by setting QMAKE_LIBDIR to the lib directory of the build tree. QMake automatically added the system library path after this value, thus allowing to correctly detect the desired libraries:
QMAKE_LIBDIR = /path/to/desired/opencvlib
I have two OpenCV versions on my PC, one installed by default in /usr and another installed by compiling the sources in a custom dir (not /usr).
The first worked just fine with Qt, the other didn't. I struggled a lot trying to make the Qt Creator work with my OpenCV compiled sources. So I added -L/opencv_lib_path but it always said 'undefined reference' for some OpenCV API I was using. It simply doesn't want to look there for the libs, it will look in LD_LIBRARY_PATH instead. I tried adding my opencv_lib_path to the LD_LIBRARY_PATH, no joy either.
The only thing that worked was Frodon's solution, just add this in your Qt .pro file and it will work.
QMAKE_LIBDIR = /path_to_installed_opencv/lib

SCons - Headers/Libraries in a non-standard location

I'm trying to use SCons to compile a program that requires a set of dependencies which I've installed in a non-standard location.
I've installed the dependencies in /home/dja/ocr. Now I'm trying to compile the main program and can't figure out how to tell SCons where to look for the libraries and headers.
I've tried (amongst others):
scons prefix=/home/dja/ocr
scons includepath=/home/dja/ocr/include libpath=/home/dja/ocr/lib
env LIBPATH=/home/dja/ocr/lib INCLUDEPATH=/home/dja/ocr/include scons
...etc...
The results are always the same:
scons: Reading SConscript files ...
Currently supported OS version: Ubuntu 10.04
Checking for C++ library iulib... no
AssertionError: :
File "/home/dja/ocr/src/ocropus/SConstruct", line 107:
assert conf.CheckLibWithHeader("iulib","iulib/iulib.h","C++");
I haven't been able to find an answer on Google.
What is the correct SCons foo to get this to work?
You need to create an environment and set appropriate variables:
env = Environment(
CPPPATH=['/home/dja/ocr/include'],
LIBPATH=['/home/dja/ocr/lib'],
LIBS=['iulib'])
env.Program('my_executable', Glob('*.c'))
The CPPPATH points to a list of C Pre-Processor Paths (Note: 3 P's). LIBPATH points to where your libraries reside. Finally, LIBS is a list of libraries to link with your program.
Unlike with make and its conventions for certain environment variables or the --with-X options to configure, the author of the SConstruct needs to provide a way for a user to specify overrides. By default, scons doesn't read build variables from the environment.
There are various ways of handling user configuration (see Variables which I just learned about), but I'm not aware of widely honored conventions. And for the user in your position, you need to rely on the author writing build documentation or a decent scons --help description, or resort to reading the SConstruct yourself (which you sometimes have to resort to with badly written unconventional Makefiles).
BTW, I would be happy to be corrected on this if my knowledge of scons is out of date.
It seems it's possible to do this by editing the SConstruct file: http://osdir.com/ml/programming.tools.scons.user/2005-09/msg00060.html
This is pretty lame - is there a better general way?
(In this case, reading the SConstruct file showed there was a special provision for providing a path to the dependency specifically, so I've solved the immediate problem but not the general one.)
I found passing LINKPATH="-L/blah/" as an environmental variable to scons worked, when passing LDFLAGS="-L/blah/" did not.
sudo scons --32 --libpath=/home/test/project/stage/lib/ --cpppath=/home/test/project/boost/ --prefix=/home/test/mongClient/output --dbg=on --opt=on install
Where libpath is for linking the library from non-standard location. cpppath is for including the header files from non-standard location.

Globally use Google's malloc?

I'd like to experiment with Google's tcmalloc on Linux... I have a huge project here, with hundreds of qmake generated Makefile's... I'd like to find a way to get gcc to globally link against tcmalloc (like it does with libc)... Is this possible? Or will I have to edit every Makefile?
(I'd prefer not to edit all the pro files as there are hundreds of them)
(Also, we've already tried the LD_PRELOAD method and it's not working quite right)...
How do your makefiles access the compiler (gcc/g++/cc/c++)?
If it's just by name (g++), and not by explicit path (/usr/bin/g++), you can simply create a replacement g++ in whatever directory you prefer, and prepend that directory to your path.
E.g.: Create a ~/mytmpgccdir/g++ file:
#!/bin/tcsh -f
exec /usr/bin/g++ -Lfoo -lfoo $*:q
Adding whatever extras (-Lfoo -lfoo) you like, either before or after the other arguments ($*:q).
Then pre-pend it to your path and make normally.
#tcsh version
% set path = ( ~/mytmpgccdir/ $path:q )
% make clean
% make
p.s. If it is by explicit name, you may be able to override it on the command line. Something like: make all GCC=~/mytmpgccdir/gcc
p.p.s If you do use LD_PRELOAD, you might want a script like this to setenv LD_PRELOAD before running your program. Otherwise it's easy to wind up LD_PRELOAD'ing on every command like /bin/ls, make, g++, etc.
First, check the qmake documentation. There is an easy way to specify (in a .pro file) that a certain library should always be linked in.
Also, since you are just experimenting, simply use LD_PRELOAD - no recompilation necessary:
LD_PRELOAD="/usr/lib/foo/libtcmalloc.so" ./your_program
You do not have to have linked "your_program" against google's tcmalloc library.

How can I add a default include path for GCC in Linux?

I'd like GCC to include files from $HOME/include in addition to the usual include directories, but there doesn't seem to be an analogue to $LD_LIBRARY_PATH.
I know I can just add the include directory at command line when compiling (or in the makefile), but I'd really like a universal approach here, as in the library case.
Try setting C_INCLUDE_PATH (for C header files) or CPLUS_INCLUDE_PATH (for C++ header files) environment variables.
As Ciro mentioned, CPATH will set the path for both C and C++ (and any other language).
On Windows these may be set to semicolon-separated lists. On most other platforms they may be set to colon-separated lists.
More details in GCC's documentation.
Create an alias for gcc with your favorite includes.
alias mygcc='gcc -I /whatever/'
Just a note: CPLUS_INCLUDE_PATH and C_INCLUDE_PATH are not the equivalent of LD_LIBRARY_PATH.
LD_LIBRARY_PATH serves the ld (the dynamic linker at runtime) whereas the equivalent of the former two that serves your C/C++ compiler with the location of libraries is LIBRARY_PATH.
A gcc spec file can do the job, however all users on the machine will be affected.
See HOWTO Use the GCC specs file

Resources