Make ld ignore directory from /etc/ld.so.conf - c++

TL,DR:
Is there a way for me (no root access) to make the linker (invoked by gcc) unaware of the contents of a directory contained in /etc/ld.so.conf after it has been cached via ldconfig?
In Detail:
I'm trying (and failing) to compile HTCondor on a custom linux distro without root access. For various reasons (see below) I believe that the problems I encounter are related to the fact that there are two versions of libssl and two versions of libcrypto installed on this machine. The newer version (1.0.0) of each of these is located at /usr/lib64 and an older version (0.9.8) is kept at /usr/local/lib64 for compatibility reasons. /etc/ld.so.conf contains both of these paths, so the linker knows about both.
During compilation I get an error
../condor_utils/libcondor_utils_8_7_9.so: undefined reference to `ERR_remove_thread_state'
since, for some reason, libcondor_utils_8_7_9.so is linked against libcrypto.so.0.9.8, while ERR_remove_thread_state was introduced in 1.0.0. It appears exactly once in the source code:
#if OPENSSL_VERSION_NUMBER < 0x10000000L
ERR_remove_state( 0 );
#elif OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
ERR_remove_thread_state( 0 );
#endif
so the preprocessor seems to make its decision based on version 1.0.0.
This question made me aware of this blog post, so I tried surrogating cpp with the following script:
#!/bin/bash
/usr/bin/gcc -Wl,-rpath-link="/usr/lib64",-rpath="/usr/lib64" "$#"
to no avail, unfortunately.
Just for the heck of it, I also tried commenting the prepocessor directives in the source code snippet above to force the selection of ERR_remove_state. This results in the linker warning me that libssl.so.1.0.0 may conflict with libssl.so.0.9.8 and, unsurprisingly, produces another "undefined reference" error.
EDIT:
The problem turned out not to be related to the linker at all. See my answer. However, out of curiosity, I'll leave the question open to see if anyone has a solution for it in its original formulation.

The comments by #user463035818 and #jww pointed me in the right direction to solve my specific problem, which turned out not be related to the linker directly.
Condor uses cmake as build system, so obviously it makes more sense to try to solve this at the cmake level (n00b here). Somewhere in the depths of all the things cmake does it finds both versions of the libraries and mixes them up for some reason. Invoking find_library with a specific version as per this answer in the main CMakeLists.txt solves that problem although it leaves a bad taste of dirty workaround in my mouth.
Making cmake ignore a certain directory when looking for libraries should not be hard, according to the docs. I haven't tried it, though.

Related

Mingw64 Linker error when trying to include -lhid [duplicate]

Context: I'm using Qt 5.9.3 on Windows, building for MinGW 32-bit. The Qt part is a side issue though - the problem seems to be with MinGW. The version of MinGW is 4.3.0, supplied prebuilt as part of the Qt installation.
I'm building a library which talks to a USB device over HID. Everything compiles fine, but it fails at the link stage with
./..\..\object\debug\usb_hid_device.o: In function `ZN8MyApp3USB5Win3213getDevicePathB5cxx11Ell':
<MYPATH>/../../source/win32/usb_hid_device.cpp:99: undefined reference to `HidD_GetAttributes(void*, _HIDD_ATTRIBUTES*)#8'
./..\..\object\debug\usb_hid_device.o: In function `ZN8MyApp3USB5Win3214CHIDDeviceImplC2EllRNS_15LogPerComponentE':
<MYPATH>/../../source/win32/usb_hid_device.cpp:200: undefined reference to `HidD_FlushQueue(void*)#4'
The linker command is
g++ -shared -mthreads -Wl,-subsystem,windows -Wl,--out-implib,<MYPATH>\bin\debug\libusb_hid_comms.a -o <MYPATH>\bin\debug\usb_hid_comms.dll object_script.usb_hid_comms.Debug -lhid -lsetupapi -LC:\Qt\Qt5.9.3\5.9.3\mingw53_32\lib C:\Qt\Qt5.9.3\5.9.3\mingw53_32\lib\libQt5Guid.a C:\Qt\Qt5.9.3\5.9.3\mingw53_32\lib\libQt5Cored.a
If I omit -lhid I get the same errors. I also get the same errors if I remove -lhid and explicitly set the path and filename to libhid.a. If I deliberately mistype the path and filename, it comes up with an error, so I know the command-line is getting parsed correctly. But for whatever reason, MinGW appears to not be linking with one of its own library files.
I've also tried removing -lsetupapi and I get the linker errors I'd expect for the functions defined in there. Likewise the Qt library files. But it seems that specifically for libhid.a, MinGW can see the library file but just isn't going to link with it.
Has anyone else seen this? Or can anyone else with the same (or similar) version of MinGW confirm or deny that they can link with libhid.a? Or is there something obviously wrong with what I'm doing?
I've just found the answer. I'm posting an answer myself so that other people know in future, because I think this is still a valid question which people might want to know about.
The problem is the include file hidsdi.h. The majority of other header files which pull in Win32 API calls have extern "C" around the function declarations. However this one doesn't! The result is that we end up with C++ name mangling for linker symbols, instead of the C-style "_" in front of the linker symbols.
The solution is to use
extern "C"
{
#include <hidsdi.h>
}
and then everything works fine.
The version of hidsdi.h with the older version of MinGW (which I'm porting from) did have that protection around the function declarations. However it looks like it's gone in the newer version.

Gurobi and C++- How it works together using Clion

First of all I am complete new to C++, so if you know the answer please be patient with me ;). Here my problem:
I wanna solve an IP with Gurobi in a C++ Code. The Code itself seems fine since there are no expression marked as errors. However when I run the Code I get the following error report:
Undefined symbols for architecture x86_64:
and many lines like that:
"GRBLinExpr::GRBLinExpr(GRBVar, double)", referenced from:
bridge_problem::max_flow_lp(time_expanded_network&, lemon::ListDigraph&, lemon::DigraphExtender<lemon::ListDigraphBase>::ArcMap<int>&, lemon::DigraphExtender<lemon::ListDigraphBase>::ArcMap<int>&, lemon::DigraphExtender<lemon::ListDigraphBase>::NodeMap<int>&) in bridge_problem.cpp.o
I suppose that the mistake is in my CMakeList.txt file. This file was automatically created since I am using Clion and for including gurobi I entered those additional lines:
include_directories(/Library/gurobi604/mac64/include)
link_directories(/Library/gurobi604/mac64/lib/libgurobi_c++.a)
link_directories(/Library/gurobi604/mac64/lib/libgurobi60.so)
Any help is greatly appreciated and if you need any more information just let me know. (In case it is important I using a mac).
EDIT: I changed my make code since I found this one:
https://github.com/joschu/trajopt/blob/master/cmake/modules/FindGUROBI.cmake
I changed the version since I have gurobi604 but it still does not work. My new error message is:
fatal error: 'gurobi_c++.h' file not found #include "gurobi_c++.h"
I don't get it since I thought by
find_path(GUROBI_INCLUDE_DIR
NAMES gurobi_c++.h
PATHS "$ENV{GUROBI_HOME}/include"
"/Library/gurobi604/mac64/include"
"C:\\libs\\gurobi604\\include"
)
that should be easy to find. Any suggestion?
From the small excerpt of your CMakeLists.txt, I expect you should be using target_link_libraries rather than link_directories.
I'd normally recommend linking to the static version of any library rather than the shared if possible (i.e. in this case prefer "libgurobi_c++.a" over "libgurobi60.so" assuming they're the same library, just compiled differently).
So, if your exe is called MyExe, you could do:
target_link_libraries(MyExe /Library/gurobi604/mac64/lib/libgurobi_c++.a)
Also, it's almost always best to avoid specifying hard-coded paths in your CMakeLists.txt. Although your copy of "libgurobi_c++.a" lives in "/Library/gurobi604/mac64/lib/", that won't be the case for other users, or on different platforms.
You can avoid this by having CMake "find" the library, for example by calling find_library:
find_library(Gurobi NAMES gurobi_c++)
if(NOT Gurobi)
message(FATAL_ERROR "Failed to find Gurobi lib. Try setting CMAKE_PREFIX_PATH")
endif()
target_link_libraries(MyExe ${Gurobi})
Then, when you run CMake, you just need to tell it where the Gurobi library is. I'm not sure how you do that in CLion, but for example if you were running CMake from the command line, you'd do:
cmake . -DCMAKE_PREFIX_PATH=/Library/gurobi604/mac64

How to enable _LIBCPP_DEBUG_LEVEL>=2 in xcode

When reading the std library implementation I could see lots of checks enabled by #if _LIBCPP_DEBUG_LEVEL >= 2 conditions. I tried to add _LIBCPP_DEBUG_LEVEL = 3 in xcode preprocessor options, but <iterator> doesn't compile anymore:
#if _LIBCPP_DEBUG_LEVEL >= 2
__get_db()->__insert_i(this); <----- the error is on this line
#endif
Is there something else I'm missing here to use a higher debug level for the standard library?
According to the libc++ documentation:
Debug mode is currently not functional. Defining _LIBCPP_DEBUG will result in fairly nasty compile errors.
So that is probably the source of that.
Baum mit Augen's answer that _LIBCPP_DEBUG_LEVEL >= 2 standard library code for lower level iterator debugging is basically unusable, appears to still be the case with the out-of-the-box Xcode 11.6. But if you're up for extra work or just want more specifics, read on...
Enabling _LIBCPP_DEBUG_LEVEL code is enabling LLVM's Debug Mode. According to that documentation, enabling this debug mode is done by defining the _LIBCPP_DEBUG to a value of 0 (that "enables most of libc++’s assertions") or 1 (that "enables 'iterator debugging' which provides additional assertions about the validity of iterators used by the program").
In XCode 11.6, I've found that adding _LIBCPP_DEBUG=0 to a project's Debug Preprocessor Macros setting, compiles and links and indeed adds additional checks - at least checking against out of range references to std::vector elements via its [] operator. Enabling the _LIBCPP_DEBUG_LEVEL >= 2 code is done by instead setting _LIBCPP_DEBUG=1. That alone however won't fully link as not all the necessary symbols are found. Specifically, the std::__1::__libcpp_db::__insert_c(void*, std::__1::__c_node* (*)(void*, void*, std::__1::__c_node*)) symbol is reported as undefined and maybe others as well. Presumably, XCode 11.6 did not ship with this built into the standard C++ library it provides. If anybody knows better or could corroborate this, I'd appreciate hearing from them.
With the following extra work, I've been able to enable libc++'s assertions plus the additional iterator debugging capabilities:
Install a recent LLVM package somewhere that doesn't interfere with Xcode's included LLVM package. I installed LLVM 10.0.1 using Homebrew and I was able to access it then under /usr/local/Cellar/llvm/10.0.1.
Have Xcode recognize the Xcode tool chain support that this new LLVM package provides. I added a symbolic link to /usr/local/Cellar/llvm/10.0.1/Toolchains/LLVM10.0.1.xctoolchain into Xcode's /Applications/Xcode.app/Contents/Developer/Toolchains directory. I'd done that while Xcode was running and it immediately saw the new tool chain but I had to restart Xcode to get it to compile with it.
Under Xcode's "Xcode" -> "Toolchains" submenu, select the new tool chain. My setup showed "Xcode 11.7" and "org.llvm.10.0.1" and I selected the latter to accomplish this.
Add the path to the new tool chain's usr/lib directory to the LIBRARY_SEARCH_PATHS declaration for resulting executable Targets. I did this by adding /usr/local/Cellar/llvm/10.0.1/Toolchains/LLVM10.0.1.xctoolchain/usr/lib to a project's executable target "Library Search Paths" "Debug" setting.
Have the path to the new tool chain's include directory override the normal standard library's include directory. I haven't confirmed that this is necessary but did this by adding to my library and executable targets' OTHER_CPLUSPLUSFLAGS declaration the value of -nostdinc++ -I/usr/local/Cellar/llvm/10.0.1/Toolchains/LLVM10.0.1.xctoolchain/usr/include/c++/v1. From within Xcode, I'd achieved that by setting the "Other C++ Flags" setting to include this value for the targets of interest. I suspect it's probably safer to make this change at the project level than target level.
Set the COMPILER_INDEX_STORE_ENABLE declaration to NO. This prevented "Unknown argument: '-index-store-path'" errors that stopped builds right from the beginning. I used Xcode's "Enable Index-While-Building Functionality" setting and set it to "No" for this.
Add _LIBCPP_DEBUG=1 to the GCC_PREPROCESSOR_DEFINITIONS declaration for the project. Did this by adding it to Xcode's "Preprocessor Macros" "Debug" setting.
For related Q&A about this, see Is it possible to enable _LIBCPP_DEBUG2 in the current Xcode 4.6.1 toolchain on Mountain Lion?.

GCC and Include File Troubles

I've been having some difficulty compiling a piece of C++ code for the physics engine Bullet Physics, and was hoping to get some advice.
This is my first time using gcc as a compiler, and including directories for compiling in general, so I'm going to give my whole process of problem-solving because I'm not sure where I went wrong or what the pertinent information is.
When I first tried to compile the code I got a fatal error about "No such error or directory", so I decided to add the directory with the -I option (1). It fixed the first error, but another popped up. Again, I was able to make the error go away with a -I option to the directory needed(2).
Then I got a whole long list of errors like the following:
main.cpp:(.text+0x33): undefined reference to 'RagdollDemo::initPhysics()'
main.cpp:(.text+0x84): undefined reference to 'glutmain(int, char**, int, int, char const*, DemoApplication*)'
/tmp/cc4MqhHm.o: In function '__static_initialization_and_destruction_0(int, int)':
main.cpp:(.text+0xe7): undefined reference to `std::ios_base::Init::Init()'
I tried a few different things, but the solution ended up using my home bullet folder (or usr/local/include/bullet/) with the --sysroot option (3).
This created a lot of errors for the C++ header files, and then I linked to a few more directories with -I (4-5), but at after one of the added directories the same set of errors that I thought I solved with the --sysroot addition popped up again (6).
I can't tell what to do now. I would guess that declaring the bullet folder as my root makes it impossible for the compiler to find the required C++ files in my actual root directories, but I don't what to do about that... and when I tried including the C++ files I needed, the compiler seemingly forgot I told it to use bullet as my root.
Final compilation I tried before I gave up and realized asking for help might be better than spending 3 hours looking at documentation without any idea of what the exact problem is. Numbers correspond to the steps above.
gcc
(3)--sysroot=/home/josh/bullet-2.82-r2704/
(1)-isystem/home/josh/bullet-2.82-r2704/Demos/OpenGL/
(2)-isystem/home/josh/bullet-2.82-r2704/src/
(4)-I/usr/include/
(5)-I/usr/include/c++/4.8
(6)-I/usr/include/x86_64-linux-gnu/c++/4.8/
./main.cpp
I'm using Ubuntu 14.04 LTS and my OS and emacs 24.3.1 as my IDE.
Any help would be greatly appreciated.
Best,
Josh
What you are seeing is not include issue. Linker is failing to link with symbols. You need to link with proper library, for example lglut

Compiler doesn't find reference to zip_get_num_entries on Windows

I want to use libzip in my program in C++ to extract files from a zip archive. So firstly, I get the number of files in it, get their names and read them. To get the number of files, I use 'zip_get_num_entries'. Its prototype is:
zip_uint64_t zip_get_num_entries(struct zip *, int)
And the way I use this function:
int nbrEntries(0);
zip *archive = zip_open("myZip.zip", 0, 0);
nbrEntries = zip_get_num_entries(archive, 0);
When I wrote this code, Code::Blocks suggested me zip_get_num_entries, so there's no problem of header. But when I compiled, the compiler (MinGW) told me that:
undefined reference to `_imp__zip_get_num_entries'
So I tried its deprecated equivalent, zip_get_num_files and it worked. I included to the project libzip.dll.a that I made with CMake. I had two files: libzip.dll and libzip.dll.a.
I'm sure it's a library problem (notice that I didn't have this problem on MacOS) but I don't know how to solve this. Thank you!
EDIT: I searched their website and read that the implementation of zip_get_num_files was new when they released the library available on the website. So I searched in their Mercurial repo and found versions that were released 2 days ago (a little bit newer than the release on the website, which has almost 1 year). I built it with CMake and it worked!
"Undefined reference" means that there is no definition/implementation (as opposed to declaration/prototype) of the function available. You forgot to link the library. Since you use MinGW with g++, it will take something like -lzip on the command line or as parts of LDFLAGS.
There is a chance that you misconfigured something, too - in which case the symbol name may be different depending on a define. But the most likely case is that you forgot to link the dependency.
I finally succeed to use zip_get_num_entries! I searched their website and read that the implementation of zip_get_num_files was new when they released the library available on the website. So I searched in their Mercurial repo and found versions that were released 2 days ago (a little bit newer than the release on the website, which has almost 1 year). I built it with CMake and it worked!