I know that ~fprebuilt-module-path` can set the module search path in clang, but how to set module search path in GCC?
Related
I am having an issue when trying to cross-compile (for an arm target) and including packages through cmake.
Compilation works fine when compiled locally and also when cross-compiled without package dependencies.
My toolchain file is:
cmake_minimum_required(VERSION 3.3)
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(CMAKE_FIND_ROOT_PATH /path/to/sysroot/)
set(CMAKE_SYSROOT /path/to/sysroot/)
set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
And in the CMakeFileList I have a few find_packages:
find_package(pack1 REQUIRED)
find_package(pack2 REQUIRED)
message("--${pack1_INCLUDE_DIRS}--")
message("--${pack2_INCLUDE_DIRS}--")
include_directories(${pack1_INCLUDE_DIRS})
include_directories(${pack2_INCLUDE_DIRS})
When displaying the include directories variables, only the first one in the list is prefixed with the sysroot path. I got something like this:
--/path/to/sysroot/usr/include;/usr/include;/usr/include/xmlrpcpp--
Of course the compilation failed, as some headers do not correspond to the target system.
Why is cmake not prefixing the entire list of directories (they are present in the sysroot folder)?
Aren't CMAKE_SYSROOT and set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) sufficient to get cmake to look only in this directory or am I missing something here?
Note: there is no difference with and without the set(CMAKE_FIND_ROOT_PATH /path/to/sysroot/) in the toolchain instructions.
Edit 1:
Explicitly setting the include paths (${pack1_INCLUDE_DIRS} and ${pack2_INCLUDE_DIRS}) to point only to the sysroot path does solve the compilation issue but then lead to a linker error (no explicit message) which suggests that 1)the extra /usr/include entries are the problem and 2) the ${pack1_LIBRARIES} variables are also incorrect.
Edit 2:
Following #Tsyvarev answer which explains why this cannot be directly achieved. One solution (a bit hacky) is to extract the name of the libraries to be included from the find_package and force cmake to look for them in the sysroot folder. The code below does work for my use case:
#Reset libraries towards sysroot only
foreach(lib_path ${pack1_LIBRARIES} ${pack2_LIBRARIES})
string(REPLACE "/" ";" lib_path_list ${lib_path}) #Breakdown path in list
list(REVERSE lib_path_list)
list(GET lib_path_list 0 lib) #Get last element (library name)
find_library(new_path ${lib} PATHS ${CMAKE_SYSROOT}) #Force to look for it in actual sysroot path
list(APPEND LIBRARIES ${new_path}) #Add it to LIBRARIES list
unset(new_path CACHE) #Clear variable to allow new search
endforeach()
Variable CMAKE_SYSROOT (and CMAKE_FIND_ROOT_PATH) re-roots only those paths, which are searched by different find_* commands: find_library, find_path, find_package(only search path for package file is modified).
E.g. if find_library searches under /usr/lib by default, then with CMAKE_SYSROOT set it will search under ${CMAKE_SYSROOT}/usr/lib instead.
However, if one calls
include_directories("/usr/include")
then the /usr/include path remain unchanged even when cross-compiling.
If find_package(pack1) is run in MODULE mode and uses Findpack1.cmake script for locate settings of pack1 package, then that Findpack1.cmake script would use find_library and find_path calls. Thus, setting CMAKE_SYSROOT would force this script to search libraries and headers under the sysroot and return appropriate paths.
But if find_package(pack1) is run in CONFIG mode and uses pack1Config.cmake script for locate settings of pack1 package, then that pack1Config.cmake could use absolute paths of the libraries and include directories. In that case CMake does NOT transform these absolute paths, so they become wrong when cross-compiling.
Actually, CMake provides mechanisms and rules which could help in writing relocatable XXXConfig.cmake scripts. But not all config scripts follow these rules.
If a project pack1 provides pack1Config.cmake script which is non-relocatable in terms of cross-compiling, then you need to build this project as cross-compiled with the same sysroot.
Below configuration won't recursively append all the sub directories to your include paths.
set(CMAKE_SYSROOT /path/to/sysroot/)
In your code the include "*.h" should be relatively against to /path/to/sysroot/.
Instead of using the toolchain file, try to pass --sysroot from your cmake command line which should always work.
Specifically, I want to include opencv from my/path/to/opencv/release where my own opencv is built other than the system's opencv lib in /usr/local/include. How can I set cmake to achieve this? I'm using Ubuntu 14.04.
To provide an example, below is a Find-CMake file for the Luajit library. Your CMake project has one that's probably called something like "FindOpenCV.cmake". It most likely has a default installation path that was manually added, such as: "/usr/include/luajit-2.0 /usr/local/include/luajit-2.0" and you would change these DIR's to your desired install directory. If the default path is contained in a variable, you could either find the definition of that variable and change it (preferably through a configuration option), or override it with a string.
# Try to find Lua or LuaJIT depending on the variable ENABLE_LUAJIT.
# Sets the following variables:
# LUA_FOUND
# LUA_INCLUDE_DIR
# LUA_LIBRARY
#
SET (LUA_FOUND FALSE)
SET (LUA_INTERPRETER_TYPE "")
SET (LUA_INTERPRETER_TYPE "LuaJIT")
SET (LUA_LIBRARY_NAME luajit-5.1)
SET (LUA_INCLUDE_DIRS /usr/include/luajit-2.0 /usr/local/include/luajit-2.0)
FIND_PATH (LUA_INCLUDE_DIR lua.h ${LUA_INCLUDE_DIRS}
HINT ${LUAJIT_INCLUDE_DIR_HINT}/include)
FIND_LIBRARY (LUA_LIBRARY NAMES ${LUA_LIBRARY_NAME} PATHS /usr/lib /usr/local/lib
HINT ${LUAJIT_INCLUDE_DIR_HINT}/bin)
#...
MARK_AS_ADVANCED ( LUA_INCLUDE_DIR LUA_LIBRARY)
There are multiple ways to achieve this, you can modify a FindOpenCV.cmake file, you set the cmake variable OpenCV_DIR before the library is found https://stackoverflow.com/a/9835300/2079934, you can export the environment variable OpenCV_DIR before you run CMake https://stackoverflow.com/a/16959771/2079934.
I would recommend not to hard-code any library paths into CMakeLists.txt, that would take away all the benefits of CMake. In Linux, I would use export to set OpenCV_DIR, in other OSes CMake GUI is more common there you could edit the path variable in the GUI.
I am having problems finding the boost-log library with the findboost module of cmake.
instead of libboost_log-vc120-mt-sgd-1_57 (which is present in my boost lib diretory)
cmake searches for: libboost_log-vc120-mt-sd-1_57 which is not present.
i have tried to enable Boost_USE_DEBUG_RUNTIME at the invokation of cmake (command line parameter) and also in my cmakelists.txt file, but it has no effect ont the ABI tag of the library names cmake find searches for.
the cmake version i am using is 3.1.0
in the documentation they write:
Boost_USE_DEBUG_RUNTIME - Set to ON or OFF to specify whether to use
libraries linked to the MS debug C++ runtime
('g' tag). Default is ON.
so it should search for libboost_log-vc120-mt-sgd-1_57 by default, also in this bug report, they introduced the Boost_USE_DEBUG_RUNTIME flag, and aknowledged that it should be set to on by default in order to not break previous behavior.
Ok i have found an answer to my problem, as it turned out there were 2 configurations missing in my example first,
Variable MSVC musst be set to true (which causes the ABI tag to contain the g value)
second,
variable CMAKE_FIND_LIBRARY_SUFFIXES is a list which must be set to the value lib dll
My LIBRARY_PATH environment variable has a custom directory in it: /cs/public/lib/pkg/opencv/lib.
But, when I use g++ --print-search-dirs, I get this instead:
libraries: =
/cs/public/lib/pkg/opencv/lib/x86_64-suse-linux/4.6/:
/cs/public/lib/pkg/opencv/lib/../lib64/:
/usr/lib64/gcc/x86_64-suse-linux/4.6/:
/usr/lib64/gcc/x86_64-suse-linux/4.6/../../../../x86_64-suse-linux/lib/x86_64-suse-linux/4.6/:
/usr/lib64/gcc/x86_64-suse-linux/4.6/../../../../x86_64-suse-linux/lib/../lib64/:
/usr/lib64/gcc/x86_64-suse-linux/4.6/../../../x86_64-suse-linux/4.6/:
/usr/lib64/gcc/x86_64-suse-linux/4.6/../../../../lib64/:
/lib/x86_64-suse-linux/4.6/:
/lib/../lib64/:
/usr/lib/x86_64-suse-linux/4.6/:
/usr/lib/../lib64/:
/cs/public/lib/pkg/opencv/lib/:
/usr/lib64/gcc/x86_64-suse-linux/4.6/../../../../x86_64-suse-linux/lib/:
/usr/lib64/gcc/x86_64-suse-linux/4.6/../../../:
/lib/:
/usr/lib/
Why does g++ look in these alternatives and a whole bunch of other system locations before what I explicitly specify in the LIBRARY_PATH variable, and where is this documented?
I would understand if system defaults were searched before LIBRARY_PATH and LIBRARY_PATH/../lib64, etc, but g++ puts LIBRARY_PATH/../lib64, then system paths, then LIBRARY_PATH. Where is this ordering documented?
My g++ version is g++ (SUSE Linux) 4.6.2
My OS is openSUSE 12.1 (x86_64)
A similar question was asked here:
g++ searches /lib/../lib/, then /lib/
These scary-looking search paths are determined at least in part when the compiler itself it built, for example during the configure phase. It's clear that it goes beyond environment variables because it's possible to have multiple copies of GCC installed and have each of them give different results for gcc --print-search-dirs. Also noting that g++ --print-search-dirs and gcc --print-search-dirs give different results points out that the g++ wrapper is also affecting the search path. Besides configure/build time differences, GCC is definitely aware of the path where its own executable is, and will search subdirectories of that path. A lot of this alchemy can be found in the GCC documentation:
http://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/Directory-Options.html#Directory-Options
http://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/Environment-Variables.html#Environment-Variables
As far as I know, the most forceful thing that you can without compiling your own copy of GCC is to specify your custom libraries using the -L option. The reason I say this is because -L is searched before e.g. LIBRARY_PATH (see the above link on environment variables). In order to make it more tolerable you could add an alias for g++ including the -L option in your .bashrc file.
If you want a definitive answer then downloading a copy of the GCC source code is one way. For example, in gcc.c the following highly suggestive comment appears:
/* Build a list of search directories from PATHS.
PREFIX is a string to prepend to the list.
If CHECK_DIR_P is true we ensure the directory exists.
If DO_MULTI is true, multilib paths are output first, then
non-multilib paths.
This is used mostly by putenv_from_prefixes so we use `collect_obstack'.
It is also used by the --print-search-dirs flag. */
However the function that follows the comment is not very obvious.
This is multilib at work - a mechanism which allows for having libraries (but also the whole compilation and build toolchain) for multiple architectures on a single machine. This Wiki states that "The multilib suffix is appended to all directories searched for libraries by GCC and passed via -L options to the linker. The linker itself does not have any particular knowledge of multilibs, and will continue to consult its default search directories if a library is not found in the -L paths. If multiple orthogonal ABI-changing options are used in a single compilation, multiple multilib suffixes can be used in series.".
So, according to the above description, the architecture marker string or different variants thereof are appended to each library search path the compiler receives since it doesn't differentiate between default and custom paths. Your custom path is first in the row, but it undergoes the same "expansion" process as other paths.
Due to the need to handle i386 compatibility, multilib mechanisms seem to now be used by default on most x64 distros, which in practice means most of the installations out there.
I have the exact same problem on:
Fedora 17, gcc 4.7 and gcc 4.3
CentOS 6.3, gcc 4.4
Unubuntu 12, gcc 4.6
So it looks like this is a problem with most gcc versions. Probably this strange behavior first appeared in gcc 4.2 at least according to this.
I tried duping the specs and playing with them. It looks like the *multilib spec is used to append specific strings depending on the platform. For example my original spacs looked like:
*multilib:
. !m64 !m32;64:../lib64 m64 !m32;32:../lib !m64 m32;
When I changed 64:../lib64 to 64:../lib then instead of ../lib64 gcc appended ../lib. But I couldn't fully decipher the meaning of *multilib or any of the other specs.
This answer attempts to summarize the search path behaviors for both GCC and Clang.
GCC
Include path: for a command-line of the following format:
CPLUS_INCLUDE_PATH=EDIR g++ -IIDIR -isystemSDIR
the following list of directories are used as search paths for #include <...>:
IDIR # '-I' directories.
SDIR # '-isystem' directories.
EDIR # *_INCLUDE_PATH directories.
GCCDIR/include/c++/GCCVER # libstdc++ directory (C++).
GCCDIR/include/c++/GCCVER/GCCARCH # libstdc++ directory (C++).
GCCDIR/include/c++/GCCVER/backward # libstdc++ directory (C++).
GCCDIR/lib/gcc/GCCARCH/GCCVER/include # GCC arch-specific directory.
/usr/local/include/GCCARCH # Local arch-specific include directory.
/usr/local/include # Local include directory.
GCCDIR/include # GCC include directory.
GCCDIR/lib/gcc/GCCARCH/GCCVER/include-fixed # GCC include-fixed directory.
/usr/include/GCCARCH # System include arch-specific directory.
/usr/include # System include directory.
Library path: for a command-line of the following format:
LIBRARY_PATH=EDIR gcc -BBDIR -LLDIR
the following arguments are passed to the linker:
-LLDIR # '-L' directories.
-LBDIR # '-B' directories.
-LEDIR/../libXX # Multilib directories from LIBRARY_PATH.
-LGCCDIR/lib/gcc/GCCARCH/GCCVER # GCC arch-specific library directory.
-LGCCDIR/libXX # GCC multilib library directory.
-L/libXX # System multilib library directory.
-L/usr/libXX # System multilib library directory.
-LEDIR # LIBRARY_PATH directories.
-LGCCDIR/lib # Other GCC libraries.
Clang
Include path: for a command-line of the following format:
CPLUS_INCLUDE_PATH=EDIR clang++ --gcc-toolchain=GCCDIR -BBDIR -IIDIR -isystemSDIR
the following list of directories are used as search paths for #include <...>:
IDIR # '-I' directories.
SDIR # '-isystem' directories.
EDIR # *_INCLUDE_PATH directories.
# If -stdlib=libstdc++ is used:
GCCDIR/include/c++/GCCVER # libstdc++ directory from the selected GCC toolchain (C++).
GCCDIR/include/c++/GCCVER/GCCARCH # libstdc++ directory from the selected GCC toolchain (C++).
GCCDIR/include/c++/GCCVER/backward # libstdc++ directory from the selected GCC toolchain (C++).
# If -stdlib=libc++ is used:
CLANGDIR/include/c++/v1 # libc++ directory (C++).
/usr/local/include # Local include directory.
CLANGDIR/lib/clang/CLANGVER/include # Clang include directory.
/include # System include directory.
/usr/include # System include directory.
Library path: for a command-line of the following format:
LIBRARY_PATH=EDIR clang --gcc-toolchain=GCCDIR -BBDIR -LLDIR
the following arguments are passed to the linker:
-LLDIR # '-L' directories.
-LGCCDIR/lib/gcc/GCCARCH/GCCVER # GCC arch-specific library directory.
-LGCCDIR/libXX # GCC multilib library directory.
-L/libXX # System multilib library directory.
-L/usr/libXX # System multilib library directory.
-LGCCDIR/lib # Other GCC libraries.
-LCLANGDIR/lib # Clang libraries.
-L/lib # System library directory.
-L/usr/lib # System library directory.
-LEDIR # LIBRARY_PATH directories.
Summary
The search path for includes are pretty much the same in both GCC and Clang. C++-specific paths are omitted if the C frontend is used in both cases. Library search paths differ substantially between GCC and Clang, notably the presence of -B directories and the odd manipulation of LIBRARY_PATH in the GCC frontend.
The library search paths are the same for both C and C++ frontends. Other library search paths are introduced by the linker itself. The following excerpt comes from the vanilla linker script for GNU Binutils:
# Multilib library directories.
SEARCH_DIR("BINUTILSDIR/BINUTILSARCH/libXX");
SEARCH_DIR("BINUTILSDIR/libXX");
SEARCH_DIR("/usr/local/libXX");
SEARCH_DIR("/libXX");
SEARCH_DIR("/usr/libXX");
# Traditional library directories.
SEARCH_DIR("BINUTILSDIR/BINUTILSARCH/lib");
SEARCH_DIR("BINUTILSDIR/lib");
SEARCH_DIR("/usr/local/lib");
SEARCH_DIR("/lib");
SEARCH_DIR("/usr/lib");
It is also imperative to note that library dependencies are not searched for inside the directories listed above. These exclusively rely on -rpath and -rpath-link options passed to the linker, or else they get resolved from the default system library paths. Thus it might be useful to produce both -L and -rpath-link arguments in order to guarantee that the correct libraries are linked.
Finally, special files (such as the CRT objects) are searched for only in -B directories. In Clang, special files are also searched inside the selected GCC toolchain. Other factors (spec files, distribution-specific configuration) might change some or all of the above.
Looks like it's needed for cross-compiling. From the ChangeLog:
Wed Mar 29 14:53:23 1995 Jim Wilson <wilson#cygnus.com>
* gcc.c (process_command): Delete code modifying gcc_exec_prefix.
(main): Put it here after last use of gcc_exec_prefix. For cross
compiler, set startfile_prefixes if gcc_exec_prefix is set and
standard_startfile_prefix is a relative path.
startfile_prefixes is what is being printed out with the search-dirs flags. From gcc/gcc.c:
if (print_search_dirs)
{
printf (_("install: %s%s\n"), standard_exec_prefix, machine_suffix);
printf (_("programs: %s\n"), build_search_list (&exec_prefixes, "", 0));
printf (_("libraries: %s\n"), build_search_list (&startfile_prefixes, "", 0));
return (0);
}
The compiler will first look at the default paths then for the others.
How does it sorted when you print I don't now, but it is documented here, 3.19 Environment Variables Affecting GCC.
The paths are defined by the built-in specs. Specs define how the pipeline processes the source code to obtain a result. GCC just drives the compilation.
You can give GCC your own spec file via -spec=, and you can get the built-in specs with -dumpspecs IIRC.
This is probably explained somewhere in the GCC manual.
I require a very simple mechanism in my application, where my project is built as a shared library '.so' or '.dll', but what I want is:
ExampleAppOne.so
I get:
libExampleAppOne.so -> libExampleAppOne.so.1.0.0
libExampleAppOne.so.1 -> libExampleAppOne.so.1.0.0
libExampleAppOne.so.1.0 -> libExampleAppOne.so.1.0.0
I don't even want the 'lib' prefix. In the .pro file, all I can do is change the INSTALLS variable (that is because my third requirement IS that the library be built in a specific directory).
Also, I have a fourth, related requirement: When I ask QLibrary to load the library, I want it to specifically search for a library in a very specific path and a library that matches the EXACT name given to it. No 'lib' prefix matching, no 'version string' searching, no looking into LD_LIBRARY_PATH...
Any help is appreciated.
Regards,
rohan
add the following to you .pro file
# disables the lib prefix
CONFIG += no_plugin_name_prefix
# disable symlinks & versioning
CONFIG += plugin
Adding plugin to the CONFIG variable should disable versioning and the generation of symbolic links to the library.
I don't know of a simple way to disable the lib prefix though. You way want to dig into the provided QMake spec files to see how the default processing is implemented.