Here is my simple CMakeLists.txt file:
include_directories (${CMAKE_SOURCE_DIR}/common)
find_package(Threads)
add_library (libusbmuxd SHARED libusbmuxd.c sock_stuff.c ${CMAKE_SOURCE_DIR}/common/utils.c)
find_library (PTHREAD pthread)
target_link_libraries (libusbmuxd ${CMAKE_THREAD_LIBS_INIT})
# 'lib' is a UNIXism, the proper CMake target is usbmuxd
# But we can't use that due to the conflict with the usbmuxd daemon,
# so instead change the library output base name to usbmuxd here
set_target_properties(libusbmuxd PROPERTIES OUTPUT_NAME usbmuxd)
set_target_properties(libusbmuxd PROPERTIES VERSION ${LIBUSBMUXD_VERSION})
set_target_properties(libusbmuxd PROPERTIES SOVERSION ${LIBUSBMUXD_SOVERSION})
install(TARGETS libusbmuxd
ARCHIVE DESTINATION lib${LIB_SUFFIX}
LIBRARY DESTINATION lib${LIB_SUFFIX}
)
install(FILES usbmuxd.h usbmuxd-proto.h DESTINATION include)
This gives me an error:
CMake error at CMakeLists.txt:12 (set_target_properties):
set_target_properties called with incorrect number of arguments
CMake error at CMakeLists.txt:13 (set_target_properties):
set_target_properties called with incorrect number of arguments
Those are the second and third set_target_properties. The first set_target_properties never had that problem?
(If you haven't realized already, I'm trying to build usbmuxd-1.0.4)
The format of SET_TARGET_PROPERTIES is:
SET_TARGET_PROPERTIES(
target1 target2 ... targetM
PROPERTIES
prop1 val1 prop2 val2 ... propN valN
)
The reason for your problem is that your variables LIBUSBMUXD_VERSION and LIBUSBMUXD_SOVERSION are undefined, and so the syntax of your command is:
SET_TARGET_PROPERTIES(target PROPERTIES name)
Instead of:
SET_TARGET_PROPERTIES(target PROPERTIES name value)
To fix this, try quoting the variables; using "${LIBUSBMUXD_SOVERSION}" should ensure that it takes on the value of the empty string even if the variable is undefined, thereby adhering to the syntax.
Related
I'm not familar with cmake but in CMakeLists.txt we set the target shared library name like this.
add_library( mylib SHARED ${source_list} )
This generates libmylib.so and other settings in CMakeLists.txt are defined for mylib like
about the mylib
and also we can use shell environment variable to do some selective settings like
target_compile_definitions( mylib PRIVATE -DQQQ -D... )
Also it is possible to use shell environment variable to do some selective things.
if(defined env{MYVAR})
set(CMAKE_C_FLAGS "-g -DXYZ")
else()
set(CMAKE_C_FLAGS "-DXYZ")
endif()
I would be happy if I could set the target shared library name as a variable according to the environment variable and use that selected name variable as the shared library name in all other settings. In other words, is it possible to do things like below?
if (defined ENV{FOR_QEMU})
set_name(target_name "simlib_qemu")
else ()
set_name(target_name "simlib")
endif ()
add_library(target_name SHARED ${source_list} )
target_compile_definitions( target_name PRIVATE -DQQQ -D... )
...
You can set the output name of a target to anything you like via:
set_target_properties(target_name PROPERTIES OUTPUT_NAME "whatever")
Then instead of libtarget_name.so, you'll get libwhatever.so. You would continue to refer to the target as target_name in your CMakeLists.txt.
However, since this will only work during configure time anyway, I strongly urge you to use a normal CMake variable instead. You may initialize it from the environment if it is not set, like so:
option(FOR_QEMU "Enable if building with Qemu support" "$ENV{FOR_QEMU}")
add_library(simlib SHARED ${source_list})
target_compile_definitions(simlib PRIVATE -DQQQ -D...)
if (FOR_QEMU)
set_target_properties(target_name PROPERTIES OUTPUT_NAME "simlib_qemu")
endif ()
This way, the CMake variable FOR_QEMU is the de-facto control and it is initialized on the first execution if the matching env-var is set. It will also appear with documentation in the cache, so other developers may query the build system directly for all its configuration points. Bear in mind: CMake is not Make and reading from the environment on every configure is a surprising behavior and generally bad practice.
I would like to compile the cmake file from Manyears 1.1.2 sources, but I got the errors as below:
WARNING : manyears GUI will not be compiled because Qt4 not found
-- Buiding ManyEarsLib Library...
CMake Error at dsplib/CMakeLists.txt:75 (set_target_properties):
set_target_properties called with incorrect number of arguments.
-- Buiding RTAudio Library...
CMake Error at example/CMakeLists.txt:22 (set_target_properties):
set_target_properties called with illegal arguments, maybe missing a
PROPERTIES specifier?
And the original program has been written as below:
target_link_libraries(ManyEarsLib )
set_target_properties(ManyEarsLib PROPERTIES LINK_FLAGS ${MANYEARS_LINK_FLAGS} OUTPUT_NAME man-years)
add_executable(manyears_console manyears_console.c)
set_target_properties(manyears_console PROPERTIES LINK_FLAGS ${MANYEARS_LINK_FLAGS})
target_link_libraries(manyears_console ManyEarsLib -lm)
Could somebody tell me what is the problem and how to risolve it?
Thanks a lot.
Lun
Command set_target_properties may only set single-value properties.
But you attempt to set property LINK_FLAGS, which is generally multi-value (a list), but in your case it is simply empty. That is why first invocation detects incorrect number of arguments (it should be even), and the second invocation detects insufficient number of arguments (is should be 4 at least).
For set multi-value properties or for clear them use command set_property:
# Multi-value (or empty) property
set_property(TARGET ManyEarsLib PROPERTY LINK_FLAGS ${MANYEARS_LINK_FLAGS})
# Single-value property
set_target_properties(ManyEarsLib PROPERTIES OUTPUT_NAME man-years)
# Multi-value (or empty) property again
set_property(TARGET manyears_console PROPERTY LINK_FLAGS ${MANYEARS_LINK_FLAGS})
or even
# Multi-value (or empty) property for several targets
set_property(TARGET ManyEarsLib manyears_console PROPERTY LINK_FLAGS ${MANYEARS_LINK_FLAGS})
# Single-value property for single target
set_target_properties(ManyEarsLib PROPERTIES OUTPUT_NAME man-years)
I can pass defined variable for cmake like below(for example when I want to set PYTHON_INCLUDE_PATH=dir1).
cmake -DPYTHON_INCLUDE_PATH=dir1 ..
But what if I want to set multiple paths for this PYTHON_INCLUDE_PATH? I tried
cmake -DPYTHON_INCLUDE_PATH='dir1 dir2 dir3'
or should it be
cmake -DPYTHON_INCLUDE_PATH='dir1:dir2:dir3' (or , instead of :)
But I'm not sure it's valid. (see some other error so I am not sure yet if it's correct or not.)
I saw I can also set these defines in .cmake file like set(VARIABLE,VALUE) like below.
set(OpenCV_CUDA_VERSION 7.5)
Then what's the corresponding syntax for this set(..) form when the variable has multiple elements?
use the following syntax:
cmake -DLIST_VAR="one;two;three" ...
you can play w/ the following CMakeLists.txt:
cmake_minimum_required(VERSION 3.5)
foreach(v IN LISTS LIST_VAR)
message(STATUS "${v}")
endforeach()
I've written a cmake module for finding QCustomPlot. However, to use the shared library, one needs to #define QCUSTOMPLOT_USE_LIBRARY. I'd like to provide this define through cmake, automatically adding the definition to any project that uses QCustomPlot.
Here is a snippet of my cmake module and my current attempted solution:
SET(QCP_FOUND "NO")
IF(QCP_LIBRARY AND QCP_INCLUDE_DIR)
SET(QCP_FOUND "YES")
SET_PROPERTY(
GLOBAL
APPEND
PROPERTY COMPILE_DEFINITIONS QCUSTOMPLOT_USE_LIBRARY
)
ENDIF(QCP_LIBRARY AND QCP_INCLUDE_DIR)
However, no linkers append the -DQCUSTOMPLOT_USE_LIBRARY flag in my compilations. What's the right way to approach this problem?
There is no global property COMPILE_DEFINITIONS. But there are such properties for directory, target and source file (see documentation). So probably the closest commands for you are:
set(QCP_FOUND "NO")
if(QCP_LIBRARY AND QCP_INCLUDE_DIR)
set(QCP_FOUND "YES")
set_directory_properties(
PROPERTIES COMPILE_DEFINITIONS QCUSTOMPLOT_USE_LIBRARY
)
endif()
But I think that this kind of job is for imported targets:
add_library(QCP::qcp UNKNOWN IMPORTED)
set_target_properties(
QCP::qcp
PROPERTIES
IMPORTED_LOCATION "${QCP_LIBRARY}"
INTERFACE_INCLUDE_DIRECTORIES "${QCP_INCLUDE_DIR}"
INTERFACE_COMPILE_DEFINITIONS QCUSTOMPLOT_USE_LIBRARY
)
and usage:
add_executable(foo ...)
target_link_libraries(foo PUBLIC QCP::qcp)
SET_TARGET_PROPERTIES(
wtdbo
PROPERTIES
VERSION ${VERSION_SERIES}.${VERSION_MAJOR}.${VERSION_MINOR}
SOVERSION ${WTDBO_SOVERSION}
DEBUG_POSTFIX "d"
)
The error is:
CMake Error at src/Wt/Dbo/CMakeLists.txt:18 (SET_TARGET_PROPERTIES):
set_target_properties called with incorrect number of arguments
If I remove it it configures just fine.
Any idea why?
Thanks,
Omer
Remember that this is a macro, so symbols are replaced before being evaluated. This means that symbols that are empty strings will be replaced to nothing before being evaluated. Thus, if WTDBO_SOVERSION is "" then
SET_TARGET_PROPERTIES(wtdbo PROPERTIES SOVERSION ${WTDBO_SOVERSION})
would become
SET_TARGET_PROPERTIES(wtdbo PROPERTIES SOVERSION)
and this would trigger the error. If empty strings are valid for your purpose then surround the symbol in quotes. e.g.
SET_TARGET_PROPERTIES(wtdbo PROPERTIES SOVERSION "${WTDBO_SOVERSION}")
Are you sure you have the variables set correctly? I've checked with this CMakeLists.txt file, and it works correctly:
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
PROJECT(test CXX)
ADD_LIBRARY(wtdbo SHARED test.cc)
SET(WTDBO_SOVERSION 1)
SET(VERSION_SERIES 1)
SET(VERSION_MAJOR 0)
SET(VERSION_MINOR 0)
SET_TARGET_PROPERTIES(
wtdbo
PROPERTIES
VERSION ${VERSION_SERIES}.${VERSION_MAJOR}.${VERSION_MINOR}
SOVERSION ${WTDBO_SOVERSION}
DEBUG_POSTFIX "d"
)
However, if I comment out the SET(WTDBO_SOVERSION 1) line I get the same error message as you do. The help for set_target_properties is as follows, so you are definitely doing the right thing:
Targets can have properties that
affect how they are built.
set_target_properties(target1 target2 ...
PROPERTIES prop1 value1
prop2 value2 ...)
Set properties on a target. The
syntax for the command is to list all
the files you want to change, and then
provide the values you want to set
next. You can use any prop value pair
you want and extract it later with the
GET_TARGET_PROPERTY command.