[CMake] CMake performs search for includes/libs in non-default compiler search paths.
Michael Wild
themiwi at gmail.com
Thu Jan 27 10:06:12 EST 2011
On 01/27/2011 03:53 PM, Óscar Fuentes wrote:
> Andreas Pakulat <apaku at gmx.de> writes:
>
>> On 27.01.11 16:13:09, arrowdodger wrote:
>>> Hello. On FreeBSD everything, that distributes with system goes to /usr (i
>>> mean includes go to /usr/includes and libs to /usr/lib) and all 3d party
>>> stuff goes to /usr/local.
>>> And the compiler is intentionally set to look only in /usr/include. The same
>>> is for linker - it's looking for libs only in /usr/lib by default. So, if
>>> user want to use some 3d-party library, he should add -I/usr/local/include
>>> and -L/usr/local/lib to build command.
>>>
>>> Now, i'm using find_library() and find_path() to locate 3d-party library in
>>> such way:
>>>
>>>> find_path(FFI_INCLUDE_PATH ffi.h PATHS ${USER_DEFINED_INCLUDE_DIR})
>>>> find_library(FFI_LIBRARY_PATH ffi PATHS ${USER_DEFINED_LIB_DIR})
>>>>
>>> I'm expecting that search will not succeed until i supply CMake with
>>> additional directories to search. But it's succeeds because
>>> CMAKE_SYSTEM_PREFIX_PATH from Modules/Platform/UnixPaths.cmake is set to
>>> "/usr;/usr/local;/". And this file is included by
>>> Modules/Platform/FreeBSD.cmake.
>>>
>>> Later i'm doing:
>>>
>>>> if(${USER_DEFINED_INCLUDE_DIR})
>>>> include_directories(${FFI_INCLUDE_DIR})
>>>> endif()
>>>>
>>>
>>> On FreeBSD it leads to "No such file or directory: ffi.h" error. So here is
>>> the question: Is this a CMake bug?
>>
>> No, the bug is in your cmake code. You shouldn't use
>> USER_DEFINED_INCLUDE_DIR to decide wether to add the path to the
>> include-directories or not. Instead use the FFI_INCLUDE_PATH variable to
>> decide that, it won't hurt if FFI_INCLUDE_PATH happens to be /usr/include.
>
> FFI_INCLUDE_PATH will evaluate to TRUE whenever find_library succeeds,
> which means that the path will always be added with
> include-directories. This has two consequences:
>
> 1. It pollutes the command line for the compiler. This is ugly and
> inconvenient while debugging the build.
>
> 2. It affects the search order of include headers with subtle
> effects. An example: if you later execute another include_directories
> with a user-defined custom location for some set of headers that
> override those provided by the system, you have a problem because
> /usr/include already comes before the path you are adding.
>
>> The reason cmake searches in /usr/local in addition to /usr is simply a
>> convenience matter. Its a common prefix to have non-distribution software
>> installed in and for the same reason things like /opt/local, /opt/csw and
>> /usr/openwin are being searched for by default.
>
> That's not a convenience here. We have to
>
> if( we are on BSD )
> add paths /usr/local/include /opt/local/include etc
> same for libraries
> endif()
>
> which is ugly as hell, puts a lot of crap on the command line and may
> create conflicts due to the altered search order.
>
> IMO cmake should look by default on the directories where the compiler
> automatically looks for. All other directories should be left for the
> user to add, as he does while compiling something that picks a header or
> library from a place not included on the default search path of the
> compiler and linker.
Sorry, but that is just a *LOT* of BS. Have you actually tried it?!
Check out the following:
-----<8------
cmake_minimum_required(VERSION 2.8)
project(tmp)
####### ATTENTION, ATTENTION #######
include_directories(/usr/include /usr/include /usr/include)
file(WRITE "${CMAKE_BINARY_DIR}/foo.c.in"
"#include <stdio.h>
int main(void) {
puts(\"Hello World!\");
return 0;
}
")
configure_file("${CMAKE_BINARY_DIR}/foo.c.in"
"${CMAKE_BINARY_DIR}/foo.c" COPY_ONLY)
set(CMAKE_VERBOSE_MAKEFILE TRUE)
add_executable(foo "${CMAKE_BINARY_DIR}/foo.c")
-----<8------
Results in the following:
-----<8------
$ cmake .. && make
-- The C compiler identification is GNU
-- The CXX compiler identification is GNU
-- Check for working C compiler: /usr/bin/gcc
-- Check for working C compiler: /usr/bin/gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Configuring done
-- Generating done
-- Build files have been written to: /tmp/incdirs/build
/usr/bin/cmake -H/tmp/incdirs -B/tmp/incdirs/build --check-build-system
CMakeFiles/Makefile.cmake 0
/usr/bin/cmake -E cmake_progress_start /tmp/incdirs/build/CMakeFiles
/tmp/incdirs/build/CMakeFiles/progress.marks
make -f CMakeFiles/Makefile2 all
make[1]: Entering directory `/tmp/incdirs/build'
make -f CMakeFiles/foo.dir/build.make CMakeFiles/foo.dir/depend
make[2]: Entering directory `/tmp/incdirs/build'
cd /tmp/incdirs/build && /usr/bin/cmake -E cmake_depends "Unix
Makefiles" /tmp/incdirs /tmp/incdirs /tmp/incdirs/build
/tmp/incdirs/build
/tmp/incdirs/build/CMakeFiles/foo.dir/DependInfo.cmake --color=
Scanning dependencies of target foo
make[2]: Leaving directory `/tmp/incdirs/build'
make -f CMakeFiles/foo.dir/build.make CMakeFiles/foo.dir/build
make[2]: Entering directory `/tmp/incdirs/build'
/usr/bin/cmake -E cmake_progress_report /tmp/incdirs/build/CMakeFiles 1
[100%] Building C object CMakeFiles/foo.dir/foo.c.o
/usr/bin/gcc -o CMakeFiles/foo.dir/foo.c.o -c /tmp/incdirs/build/foo.c
Linking C executable foo
/usr/bin/cmake -E cmake_link_script CMakeFiles/foo.dir/link.txt --verbose=1
/usr/bin/gcc CMakeFiles/foo.dir/foo.c.o -o foo -rdynamic
make[2]: Leaving directory `/tmp/incdirs/build'
/usr/bin/cmake -E cmake_progress_report /tmp/incdirs/build/CMakeFiles 1
[100%] Built target foo
make[1]: Leaving directory `/tmp/incdirs/build'
/usr/bin/cmake -E cmake_progress_start /tmp/incdirs/build/CMakeFiles 0
-----<8------
That's right, -I/usr/include doesn't even show up ONCE, although I added
it three times using include_directories().
Michael
More information about the CMake
mailing list