Add linker flag during conan install - visual-c++

I'm working in a project that uses a number of external libraries. These libraries are included using Conan. The project is primarily written for Unix, but it also need to compile and run on Windows.
My current problem is that Windows defaults fopen() to be O_TEXT, while Unix expects this to be O_BINARY. I have a fix that works for my own code, simply include binmode.obj when linking to change this default to O_BINARY.
The problem is that this does not affect my third party libraries. Googling for this didn't turn up much, most suggestions seems to be based on where you are creating your own package and want flags added, rather than how to add flags when using other's packages.
What I have tried so far:
Make binmode.obj come before libraries, in case the linking order matters. Made no difference.
Added --env 'CL=link binmode.obj' to conan install, but this flag did not end up as part of the compile flags nor link flags.
Any suggestions for what I could try?
EDIT: I was wrong about "CL" taking no effect. This was caused by confusing output. But I did observe that CL seems to be applied for both compiler and linker, which makes it somewhat challenging what flags to give. Using "/link" prefix makes it work with compiler, but does not work with linker.
EDIT 2: More confusions... I didn't realize that the syntax of the CL value was: "<compile flags> /link <link flags>". It affected compile, but not link, however. So this environment variable apparently can't be used to make Conan add a linker flag for autotools based packages.

Hi Mats L welcome to our community!
I once had a similar problem and what I end up doing was quite hacky but quite simple also:
On my conan profile located at ~/.conan/profiles/default or any other profile actually I added an enviromental variable as such:
CXX=/usr/bin/clang++ -fms-compatibility. This one made me compile all the c++ sources with this flag (that can understand windows specific code).
So in your case you can run which c++ to find the location of your compiler
and edit the CXX environmental variable in the conan profile you use your final file will probably look like :
[settings]
os=Macos
os_build=Macos
arch=x86_64
arch_build=x86_64
compiler=clang
compiler.version=11
compiler.libcxx=libc++
build_type=Release
[options]
[build_requires]
[env]
CXX=c++ --required_flag
Some additional notes: You might also want this flag set on your CC enviromental variable .
It's preferable to not change the default profile but copy it (lets say on a file named default_edited_copy) and then invoke the other profile with conan ... --profile default_edited_copy

Related

How to set LD_LIBRARY_PATH from a CMake toolchain file?

On Linux, I want to create a CMake toolchain file for cross-compilation.
The compiler needs some shared libraries that are located in non-standard directories, so I have to set LD_LIBRARY_PATH before invoking it. That worked when calling the compiler from the command line, but not when calling it from CMake.
I tried to set LD_LIBRARY_PATH via set(ENV{LD_LIBRARY_PATH} "${CMAKE_CURRENT_LIST_DIR}/<shared library directory>") from the toolchain file. However the compiler complained that it couldn't find the shared libraries.
Table of contents:
Setting it in a toolchain file isn't going to do what you want.
I'm not sure why setting LD_LIBRARY_PATH before invoking the buildsystem isn't working for you.
There's a more idiomatic way in CMake to do what you want.
Setting it in a toolchain file isn't going to do what you want
I'm pretty sure the approach you are asking how to take won't work because set(ENV) just sets an environment variable that will only be known to CMake at the configure stage (not the build stage). Here's a minimal reproducible example of that:
CMakeLists.txt:
cmake_minimum_required(VERSION 3.23)
project(Foo)
set(ENV{FOO} "hello world!")
message("\$ENV{FOO} at configure time: $ENV{FOO}")
add_custom_target(echo
"${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_SOURCE_DIR}/echo.cmake"
VERBATIM
)
echo.cmake:
cmake_minimum_required(VERSION 3.23)
message("\$ENV{FOO} at build time: $ENV{FOO}")
run the following:
$ cmake -S . -B build --fresh
<...>
$ENV{FOO} at configure time: hello world!
<...>
$ cmake --build build/ --target echo
$ENV{FOO} at build time:
Since environment variables are "passed downward" to child processes and not upward, when you do set(ENV), that's just setting it in the CMake process that performs the configure step (the one invoked by the cmake -S ... command in the example above). As the example shows, CMake doesn't do anything fancy to make those environment variables known at its configure time to the generated buildsystem at build time.
I'm not sure why setting LD_LIBRARY_PATH before invoking the buildsystem isn't working for you
So I have to set LD_LIBRARY_PATH before invoking it. It works when calling the compiler from the command line, but not from CMake.
As long as you're exporting the variable for it to be made available to the shell's child processes (using the correct mechanism for whichever shell you're using), that should work. A minimal reproducible example would help here.
There's a more idiomatic way in CMake to do what you want
Try using the find_library() command. It does what its name says it does at configuration time (instead of build time). If you use it, you'll also get the benefit of your buildsystems being more cross-platform.
It has several ways of tweaking how it searches for libraries. You can read about exactly how it works in the official docs.
For your case here, one of the suitable configuration points to guide the library search would be the CMAKE_LIBRARY_PATH variable, although as you'll read about, there are other configuration points you could use as well.

Bash command: export BLAS_LIBS="-L$LAPACKHOME/lib -lblas"

Can any body explain to me what does the whole sentence mean?
I know this is to set Macro BLAS_LIBS as another string.
But I'm not sure what's the "-lblas" mean and I don't know how to use it.
Similar as the following code. "-llapack"
export LAPACK_LIBS="-L$LAPACKHOME/lib -llapack"
How can the program find out the BLAS and LAPACK libraries just by "-lblas" and "-llapack" ?
Thanks for advance.
I'm not sure why you say "just by -llapack" because that's not what is happening here. Specifically, the -L option just before it specifies a directory path to add to the library resolution path. This works roughly like PATH in the shell.
For example, with the command line fragment gcc -Lfoodir -Lbardir -lfoo -lbar, you basically instruct the linker to search the directories foodir and bardir for the library files libfoo.a and libbar.a.
The -l option is described in GCC: Options for Linking and -L and friends in the following section GCC: Options for Directory Search.
This build arrangement -- configure the build to show where the required files are before compiling -- is common for libraries, where if a user has already downloaded and compiled a required library for some other project, they don't need to rebuild it; they can just point the compiler to wherever they already have the stuff needed for this project.
Building your own libraries is becoming increasingly unnecessary anyway, as prepackaged binaries of most common libraries are available for most systems these days. But of course, if you are on an unusual platform, or have specialized needs which dictate recompilation with different options than any available prebuilt binary, you will still need to understand how to do this.

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.

How to use ccache selectively?

I have to compile multiple versions of an app written in C++ and I think to use ccache for speeding up the process.
ccache howtos have examples which suggest to create symlinks named gcc, g++ etc and make sure they appear in PATH before the original gcc binaries, so ccache is used instead.
So far so good, but I'd like to use ccache only when compiling this particular app, not always.
Of course, I can write a shell script that will try to create these symlinks every time I want to compile the app and will delete them when the app is compiled. But this looks like filesystem abuse to me.
Are there better ways to use ccache selectively, not always?
For compilation of a single source code file, I could just manually call ccache instead of gcc and be done, but I have to deal with a complex app that uses an automated build system for multiple source code files.
To bypass ccache just:
export CCACHE_DISABLE=1
For more info:
man ccache
...
If you set the environment variable CCACHE_DISABLE then ccache will just call the real
compiler, bypassing the cache completely.
...
What OS? Linux? Most packaged versions of ccache already put those symlinks into a directory, for example on my Fedora machine they live in /usr/lib64/ccache.
So you could just do
PATH=/usr/lib64/ccache:${PATH} make
when you want to build with ccache.
Most packages also install a file in /etc/profile.d/ which automatically enables ccache, by adding it to the PATH as above.
If that's the case on your system, just set CCACHE_DISABLE=1 (see man ccache for more info) in your environment to disable ccache - ccache will still be run, but will simply call the real compiler.
I stumbled across this for so many times now. For me the best solution was to do this:
export CCACHE_RECACHE=1;
From the ccache manpages:
Corrupt object files
It should be noted that ccache is susceptible to general storage problems. If a bad object file sneaks into
the cache for some reason, it will of course stay bad. Some possible reasons for erroneous object files are
bad hardware (disk drive, disk controller, memory, etc), buggy drivers or file systems, a bad prefix_command
or compiler wrapper. If this happens, the easiest way of fixing it is this:
1. Build so that the bad object file ends up in the build tree.
2. Remove the bad object file from the build tree.
3. Rebuild with CCACHE_RECACHE set.
The alternative to creating symlinks is to explicitly use ccache gcc as the C compiler and ccache g++ as the C++ compiler. For instance, if your Makefile uses the variables CC and CXX to specify the compilers, you can build with make CC="ccache gcc" CXX="ccache g++" or set it up at configure time (./configure CC="ccache gcc" CXX="ccache g++").

Resources