[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