2015-09-28 4 views
3

С некоторыми компиляторами, using pow and certain other functions in a C program requires linking to the m library. Однако некоторые компиляторы не требуют этого и будут ошибаться при подключении к библиотеке m. Почти такая же ситуация существует для C++ с std::thread и pthread, но модуль CMake FindThreads полностью устраняет это - есть ли какой-то подобный модуль для libm?Может ли CMake определить, нужно ли мне ссылаться на libm при использовании pow в C?

Каков наилучший способ определить, что делать с CMake? Это мое текущее решение, которое меньше, чем идеал, потому что есть много других компиляторов C, чем просто GCC и MSVC:

if(NOT MSVC) 
    target_link_libraries(my-c-target PUBLIC m) 
endif() 

Это работает для моих целей, но я уверен, что есть случаи, когда оно не будет и требуют ручного вмешательства пользователя, что не является забавой для тех, кто не знает об этой безвестности. В идеале я не хочу, чтобы пользователь должен был указать, является ли их компилятор weird или нет через командную строку; Я хочу автоматически обнаружить его в CMake, так как это весь смысл CMake.

+1

«* некоторые компиляторы не требуют этого и будет ошибка на ссылки на м библиотеки *» Какой из, пожалуйста? – alk

+0

@alk Я работал с неясным компилятором C для робота-микроконтроллера, который, как я знаю, не поддерживает '-lm', потому что это была первая ошибка, которую я когда-либо получал от этого компилятора. Не исключено, что мой конкретный код будет использован в таком сценарии. –

ответ

5

Вы должны использовать модуль CHECK_FUNCTION_EXISTS, чтобы проверить, можно ли использовать pow без дополнительных флагов. Если эта проверка не удалась, вы можете добавить библиотеку m в переменную CMAKE_REQUIRED_LIBRARIES и запустить снова CHECK_FUNCTION_EXISTS.

Пример кода:

include(CheckFunctionExists) 

CHECK_FUNCTION_EXISTS(pow RESULT) 
if(NOT RESULT) 
    unset(RESULT) 
    list(APPEND CMAKE_REQUIRED_LIBRARIES m) 
    CHECK_FUNCTION_EXISTS(pow RESULT) 
    if(RESULT) 
    target_link_libraries(yourtarget m) 
    else() 
    message(FATAL_ERROR "No pow() found") 
    endif() 
endif() 
+0

Хотя похоже, что он должен работать, 'CHECK_FUNCTION_EXISTS', похоже, кэширует результат, так что второй раз, когда вы его вызываете, является no-op. –

+1

О, право. Либо «unset (RESULT)», либо используйте другое имя переменной во втором вызове. – arrowd

+0

Спасибо, это сработало! Я приму свой ответ сейчас, просто не забудьте изменить его с помощью исправления. –

2

Общий способ проверки правильности кода для компилятора - try_compile.

use_pow.c:

#include <math.h> 
int main(void) {return pow(2, 2.5);} 

CMakeLists.txt:

... 
if(NOT DEFINED POW_LIBS) 
    try_compile(pow_use_m # RESULT_VAR 
       check_pow # bindir 
       use_pow.C# srcfile 
       LINK_LIBRARIES m) 
    if(pow_use_m) 
     set(POW_LIBS m CACHE INTERNAL "Libraries for use pow") 
    else() 
     set(POW_LIBS "" CACHE INTERNAL "Libraries for use pow") 
    endif() 
endif() 

... 
target_link_libraries(my-c-target PUBLIC ${POW_LIBS}) 

запись кэша POW_LIBS содержит библиотеки, необходимые для использования функции pow.