Replace AC_CHECK_LIB in CMake - cmake

I'm converting a project from Autotools to CMake.
We have a configure.ac file, with the statement:
AC_CHECK_LIB([gsuffix], [gsuffix_create], [], AC_MSG_ERROR([Can not find gsuffix library]))
I want to replace it to cmake, and not sure how (it doesn't have pkg-config)
What I need is:
check libgsuffix exists and find path.
Check gsuffix_create exists in libgsuffix
Add -lgsuffix to compilation - this I think I know how to do.
Can anyone point me to the right direction?

There is no one to one translation. In general, with CMake you don't check whether every header and every library actually works. If you find the file, you assume it will do the trick.
Maybe find_package is right for you, depending someone already wrote such a test or your library provides an according config file.
Find_library is meant to find libraries, but by name.
If you really have to check that your library works, use CheckLibraryExists.

As mentioned, did not find anyway to do this with one command.
I didn't have enough time to understand how to do something completely generic, so I can give my skeleton for a FindGSUFFIX.cmake:
FIND_LIBRARY(GSUFFIX_LIBRARY NAMES gsuffix)
INCLUDE(CheckLibraryExists)
CHECK_LIBRARY_EXISTS(gsuffix gsuffix_create ${GSUFFIX_LIBRARY} GSUFFIX_VERIFIED)
# Handle the QUIETLY and REQUIRED arguments and set PCRE_FOUND to TRUE if all listed variables are TRUE.
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(GSUFFIX DEFAULT_MSG GSUFFIX_LIBRARY GSUFFIX_VERIFIED)
MARK_AS_ADVANCED(GSUFFIX_LIBRARY)

Related

How to keep CMake generated files?

I'm using add_custom_command() to generate some files. ninja clean removes them, as it should. One of the files is intended as a default/example implementation, to be modified by the user. It is only generated if it does not already exist. I would like for ninja clean not to remove this file.
I have tried a number of things but without success:
add_custom_target(): CMake complains about the missing file unless I name it in BYPRODUCTS, but doing this also leads to removal on clean
set_file_properties(... GENERATED FALSE) doesn't work because CMake complains about the file missing.
set_directory_properties() failed in a similar way: "folder doesn't exist or not yet processed" (it does exist)
I previously generated the example implementation and just let the user copy it or model their code on it. This works, but isn't entirely satisfactory. Is my use-case so unlikely that CMake doesn't support it?
I am afraid you requirment (conceptually, have make create something which make clean does not remove) is rather unusual. I can think of two potential solutions/workarounds.
One, move the file's generation to CMake time. That is, create it using execute_process() instead of add_custom_command(). This may or may not be possible, based on whether the file-generation process (the current custom command) depends on the rest of the build or not.
Two, totally hide the example file's existence from CMake. That is, have the custom command also generate some other file (maybe just a timestamp file) and have its driving custom target depend on that one instead. Do not list the example file as ither the custom command's dependency, output, or byproduct. That way, nothing will depend on it and neither CMake nor Ninja should not care whether it exists or not, so they will not complain or try to clean it up.
If it is an example for the user, it should not be in your build folder, but in the install folder. I don't see why you would need add_custom_command or the other commands you listed.
Therefore, you have to provide install() instructions.
You can then call make install. Cleaning will not remove those and only installing again will overwrite them if necessary.
For those, who come here a long time after the original question was asked (like me), I'll write my solution:
The tool called in add_custom_command generates two files with identical content:
one that is saved in sources, never mentioned anywhere
and one that's marked as byproduct, and then is depended on
So the first one is the file we wanted in the first place.
And the second one is actually used in build process, and gets deleted on clean.
For me the issue is that I actually want to save generated files in VCS so I can track changes. And this approach gives ne what I need.

CMake find_library: why are paths in PATHS searched after default paths?

CMake documantation seems clear: unless NO_DEFAULT_PATH is specified, cmake proceeds to first search a bunch of default paths, and if the library is not found, only then it looks in the directories listed in PATHS. A few other NO_* exist, to only exclude some of cmake default paths.
I know how to overcome this behavior. E.g., I can do what's suggested here, namely, do two searches: the first with NO_DEFAULT_PATH, and the second without it. If the first succeeds, the second will be skipped. Win.
However, this question is not about how to achieve what I want (I know the hack). The question is why do I need to do that? Why doesn't cmake look first in the provided paths? It seems logic to me to use those first: if the user is specifying some hints, perhaps I should use those first, and fall back on defaults if they don't work...
Is there a good reason I am missing for the current implementation? I would assume so, I doubt folks down at cmake do things without a good reason...
Edit: when I said 'the user is specifying some hints', I was not referring to the actual HINTS argument of find_library. It was more of a generic 'hints'. However, as suggested in a comment, HINTS is indeed scanned before system paths. My concern comes from cmake's documentation:
Search the paths specified by the HINTS option. These should be paths
computed by system introspection, such as a hint provided by the
location of another item already found. Hard-coded guesses should be
specified with the PATHS option.
The fact that HINTS was not designed to receive hard coded full paths, makes me thing it may fire back in the future, so I'm not sure it is the solution. But maybe it is?

where is the list of names that cmake reserves?

Everything is in the title, but for more context informations:
I am creating a library, where all components are independent (it's only because it's easier to manage 1 git repo, really).
In that library's root folder, I have 1 sub-folder for each part of the library's components, with exactly 3 "interesting folders" (src,tests,include/components_name). I have hardcoded those folders in a foreach loop so that all actions will be done for all modules by default.
The problem seems to be that, one of the modules is named "option_parser" which is, indeed, relatively generic, and also seems to be "reserved" by cmake, and same for everything derived from it. I've tried "option_parser_test", "option_parser_tests", and other random names based on "option_parser_" root.
So, here is my question: where I can learn how to avoid names that cmake reserves?
And how can I affect them anyway to my binaries (because, I feel like it's stupid to change a project's name because of a build system. Might be a strong enough reason to switch it.)
It's really quite simple. Use these three commands to see all reserved words:
cmake --help-command-list
cmake --help-variable-list
cmake --help-property-list
The answer of Cinder Biscuits above should probably already help you.
Additionally, you should probably read CMake's own documentation regarding the CMake language and in particular the note in the "Variables" section:
Note: CMake reserves identifiers that:
begin with CMAKE_ (upper-, lower-, or mixed-case), or
begin with _CMAKE_ (upper-, lower-, or mixed-case), or
begin with _ followed by the name of any CMake Command.

CMake does not find CxxTest package

I wrote the following CMakeLists.txt in order to build a tester using CxxTest (it's almost the standard example provided by FindCxxTest):
cmake_minimum_required(VERSION 2.8)
project(tester)
set(CMAKE_INCLUDE_PATH "${CMAKE_CURRENT_SOURCE_DIR}")
find_package(CxxTest REQUIRED)
if(CXXTEST_FOUND)
include_directories(${CXXTEST_INCLUDE_DIR})
enable_testing()
CXXTEST_ADD_TEST(tester_executable runner.cpp
${CMAKE_CURRENT_SOURCE_DIR}/myTestsuite.h)
endif()
The problem is that CxxTest is not found although I have the folder cxxtest and the file cxxtest/TestSuite.h inside the directory where CMakeLists.txt exists.
I already looked into the source code of FindCxxTest.cmake to see how far it gets, but it doesn't even find the path CXXTEST_INCLUDE_DIR.
Do I have to set another search path or something? I'm testing on Windows.
find_path does not search the current list directory. That is, just because a relative path is reachable from the current CMakeLists.txt, does not mean that it will be found. You can find a complete description of the search order in the manual.
A quick and dirty solution is to add the respective directory to your CMAKE_PREFIX_PATH:
set(CMAKE_PREFIX_PATH ${CMAKE_CURRENT_LIST_DIR})
find_package(CxxTest)
More fine grained control is available via the CMAKE_SYSTEM_PREFIX_PATH, CMAKE_INCLUDE_PATH, CMAKE_LIBRARY_PATH and CMAKE_PROGRAM_PATH variables. Also, some find scripts provide means of injecting search hints without having to pollute the global variables (although FindCxxTest does not seem to offer this).
Another option is, if you anyway include the CxxTest sources at a fixed place in your source tree, to not use the the find script at all, but hardcode the paths instead.
This may feel like a dirty solution at first, but if you can really rely on the sources always being there, it's actually the cleanest and most robust way to solve this. Find scripts really only make sense when you can not say where exactly on the system the files are located.

find libavahi with cmake

I need to add libavahi-client3 to cmake dependency of my project. Also need to check libavahi-client3 and libavahi-common3 existence. Problems only with current library(avahi)
Trying to do these things:
find_package(libavahi-common3)
if(NOT libavahi-common3_FOUND)
message(ERROR " libavahi-common3 is not found")
endif(NOT libavahi-common3_FOUND)
OR this variant:
find_library(AVAHI_COMMON_LIBRARY NAMES libavahi-common3)
if(NOT AVAHI_COMMON_LIBRARY_FOUND)
message(ERROR " libavahi-common3 is not found")
endif(NOT AVAHI_COMMON_LIBRARY_FOUND)
Both do not work, i searched for something like findAvahi.cmake, but found nothing. So should i write my own search module or there is another better option?
There is currently no find script for avahi shipping with CMake, which is why your first example does not work. It is important to understand that find_package simply runs an external find script, it does not perform any searching by itself.
Your second example is broken, mixing idioms from find_library and find_package. Please read up on the documentation of find_library and find_path which will help you find the required libraries and include paths.
If you want you can turn that into a find script later (look at the scripts in CMake's module directory to get an idea what such a script should look like), which will allow you to use the more compact find_package for locating the library again. Note that writing a find script that works reasonably well on different platforms is a complex task that will require some research effort to get it right.