I am afraid the question I have might be stupid, but as I am new to kdevelop and cmake it is quite hard for me to understand how they work.
The project I tried to set up uses the libnet 1.1 library. My Question is how do I get cmake to compile and link this library so I can use it properly?
Here is what I already tried:
PROJECT(test)
include_directories("${PROJECT_SOURCE_DIR}/libnet")
add_subdirectory(libnet)
ADD_EXECUTABLE(test main.c)
target_link_libraries(test libnet)
Thank you for your Help!
It looks like libnet does not use CMake itself, so you're going to have to build it separately or make it part of your own project.
To build it separately, you have a couple of choices. You can build it (and install it if you want) and then use find_library to locate the actual libnet.a / libnet.lib file.
find_library(libnet NAMES net libnet PATHS <wherever you built it to>)
include_directories(<wherever you built it to>/include)
target_link_libraries(test libnet)
CMake provides a decent way to automate this through use of ExternalProject_Add. This is a little trickier to use, but you can make it download, extract, build and install libnet all in one command. It looks like libnet has several different ways of being built though, depending on platform, so this may not be too straightforward.
Another option would be to include the libnet sources in your own project and add it as a library via add_library. You'd need to create a list of the libnet sources, and also examine the libnet makefiles to check for any compiler flags / oddities that would need special handling in your own CMakeLists.txt
This is perhaps the best option since it gives you access to the full libnet source tree in your IDE, allows you to fine-tune the libnet build, and causes your own project to go out of date (need rebuilding) if the libnet build changes.
set(LibnetSources <list all sources and headers>)
add_library(libnet ${LibnetSources})
include_directories(${PROJECT_SOURCE_DIR}/libnet/include)
target_link_libraries(test libnet)
You can make use of file(GLOB...) to help with generating the list of libnet sources, but it's not recommended since the addition or removal of a file would not be automatically detected by CMake. You need to make sure that if you do this, you re-run cmake manually before trying to recompile. This isn't an issue if you're not planning on adding/deleting any libnet files.
Edit: Use ExternalProject Module
OK, there is a third option which is maybe the best, but can be slightly complex to set up; use CMake's ExternalProject Module. This is designed to allow building of external dependencies - even ones which don't use CMake. This is a decent article on using it.
Try replacing your CMakeLists.txt with this (only tested on Ubuntu with gcc). In short, it downloads libnet, configures it, builds it and installs it to your build tree (not to /usr/local). Your executable can then include and link to it.
# Minimum version 2.8.5 since we need ExternalProject module
cmake_minimum_required(VERSION 2.8.5 FATAL_ERROR)
project(test)
# Enable ExternalProject CMake module
include(ExternalProject)
# Set default ExternalProject root directory
set_directory_properties(PROPERTIES EP_PREFIX ${CMAKE_BINARY_DIR}/ThirdParty)
# Add libnet
ExternalProject_Add(
libnet
URL http://packetfactory.openwall.net/libnet/dist/libnet.tar.gz
TIMEOUT 30
CONFIGURE_COMMAND <SOURCE_DIR>/configure --prefix=<INSTALL_DIR>
BUILD_IN_SOURCE ON
# Wrap download, configure, build and install steps in a script to log output
LOG_DOWNLOAD ON
LOG_CONFIGURE ON
LOG_BUILD ON
LOG_INSTALL ON)
# Specify include dir
ExternalProject_Get_Property(libnet install_dir)
include_directories(${install_dir}/include)
# Add test executable target
add_executable(test main.c)
# Create dependency of test on libnet
add_dependencies(test libnet)
# Specify test's link libraries
target_link_libraries(test ${install_dir}/lib/libnet.a)
Related
My c programm(for linux) needs users to have a specific programm lets say "foo" be installed to work. I am using cmake to generate build files.
This program is to be distributed.
How can I make sure that it is installed using cmake.
I found this but it's for checking at runtime. I want to check it before building the program.
If foo provides a CMake package, use find_package to find foo:
find_package(foo REQUIRED)
# Use the foo::foo imported target or foo_EXECUTABLE cache variable
There are many built-in packages for CMake including Python and FLEX.
If foo does not provide a CMake package and you only need the path to the executable, then you can use find_program:
find_program(Foo_EXECUTABLE foo REQUIRED)
From here you can use the Foo_EXECUTABLE variable in your execute_process or add_custom_command calls.
I have to create SOAP services in C using axis2C. But since axis2C is kind of not maintained properly as per this question, I have to use axis2C unofficial source code. But I could not see configure file to build the sources. How should I build this. I checked all the documentation both in here and in the github repo but no luck. All points to the axis2C official documentation. Should I copy the sources from unofficial to official code and try with the configure script in official folder ?
This project probably uses the GNU build system. In this system, ./configure is a portable shell script that is automatically generated from hand-written input files, the main file is configure.ac.
So, distribution packages of the source will contain ./configure, therefore enabling anyone on any platform with a sh-compatible shell and a make utility to build the software. But as it is a generated file, you will not find it in source-code repositories, e.g. on github.
To build a package using the GNU build system directly from source controls, you have to use the GNU autotools yourself to generate ./configure. In order to do this, install the following packages:
autoconf -- generates ./configure from ./configure.ac.
automake -- generates portable makefile templates Makefile.in from Makefile.am (those templates are then filled with values by the ./configure script to write the final Makefiles)
libtool -- tools for building dynamic shared objects on different platforms
Then, the command autoreconf -i given in the root of your source package should generate the ./configure script for you.
Note that there are packages providing a script ./autogen.sh (or similarly named). If this is there, you should call it instead of running autoreconf -i yourself, it might contain additional necessary preparation steps. ./autogen.sh will typically directly run the generated ./configure for you.
The title states the problem statement: I'm trying to create a CMake project utilizing the libwebsocket library, but I can't find any information for doing so.
Is there anyone who have tried this? A simple CMakeLists.txt for e.g. the test-server program would be much appreciated!
I've compiled and installed the library on my Ubuntu 14.04 machine.
EDIT: I would also like to know if anyone has experience in using the libwebsocket lib w/ C++?
EDIT 2:
After using #evadeflow's answer I'm able to run cmake and build the project. However now I get the following runtime error:
And here's an ls of the /usr/local/lib/ folder
It seems like the libwebsockets.so.7 file is not found?
From CMake:
${LIB_WEBSOCKETS_INCLUDE_DIRS} = /usr/local/lib
${LIB_WEBSOCKETS_INSTALL_DIR} = /usr/local
EDIT 3:
Solved edit 2 by:
Editing the file /etc/ld.so.conf and add /usr/local/lib.
Reference: https://lonesysadmin.net/2013/02/22/error-while-loading-shared-libraries-cannot-open-shared-object-file/
If you've already installed libwebsockets, something like this ought to work:
cmake_minimum_required(VERSION 2.8)
find_package(PkgConfig)
pkg_check_modules(LIB_WEBSOCKETS REQUIRED libwebsockets)
get_filename_component(
LIB_WEBSOCKETS_INSTALL_DIR
${LIB_WEBSOCKETS_LIBRARY_DIRS}
DIRECTORY
)
add_executable(
test-server
test-server/test-server.c
test-server/test-server-http.c
test-server/test-server-dumb-increment.c
test-server/test-server-mirror.c
test-server/test-server-status.c
test-server/test-server-echogen.c
)
target_link_libraries(
test-server
${LIB_WEBSOCKETS_LIBRARIES}
)
set_target_properties(
test-server
PROPERTIES
INCLUDE_DIRECTORIES
${LIB_WEBSOCKETS_INCLUDE_DIRS}
LINK_FLAGS
"-L${LIB_WEBSOCKETS_LIBRARY_DIRS}"
COMPILE_DEFINITIONS
INSTALL_DATADIR="${LIB_WEBSOCKETS_INSTALL_DIR}/share"
)
This is basically a stripped-down version of what's in the CMakeLists.txt file from the libwebsockets github project, without all the platform- and build-specific conditionals.
I hope this is enough to satisfy your request for a 'simple' CMakeLists.txt example. I tested it with CMake version 2.8.12.2; it should work fine as-is if you've installed libwebsockets to its default prefix of /usr/local; however, if you installed to a different location, you will need to set PKG_CONFIG_PATH in the environment from which you invoke cmake.
Also, as explained in the CMake documentation, you will need to replace DIRECTORY with PATH in the get_filename_component() invocation if you're using CMake 2.8.11 or earlier.
UPDATE: Regarding the file not found error from your follow-up comment, this is almost certainly due to libwebsocket.so[.7] not being on the linker's default path. There are at least three ways to fix this, but the easiest way to verify that this is the problem would be to just launch the app from the terminal using:
$ LD_LIBRARY_PATH=/usr/local/lib ./test-server
If it works, you know that was the issue. (Oops—I see you've figured it out in the meantime. Yeah, updating /etc/ld.so.conf is another way. Or, you can force CMake to link to the static version of libwebsockets [as described in this answer] is another. But I like your solution best.)
UPDATE: One thing that wasn't mentioned about /etc/ld.so.conf is that you generally need to run sudo /sbin/ldconfig after editing it in order to update the shared library cache. And—when setting non-default paths for a particular application—many people consider it good form to add a new 'sub-config file' in /etc/ld.so.conf.d rather than edit the global ldconfig file. (For the case of adding /usr/local/lib, though, this is such a common requirement I'd be inclined to dump it in the global config, which is what lots of Linux distros do, anyway.)
Ive been cross compiling my unit-tests to ensure they pass on all the platforms of interest, e.g. x86-linux, win32, win64, arm-linux
they unit tests require the CUnit library
So I've had to cross compile that also for each platform
That comes with its own autoconf stuff so you can easily cross-build it by specifying --host for configure
The question I have is where is the 'correct' place to have the CUnit libs installed for the various platforms? i.e. what should I set --prefix to for configure?
My initial guess was:
/usr/local/<platform>/lib/Cunit
i.e. setting --prefix /usr/local/<platform>
e.g. --prefix /usr/local/arm-linux-gnueabihf
which on sudo make install gives you:
/usr/local/arm-linux-gnueabihf/doc/CUnit
/usr/local/arm-linux-gnueabihf/include/CUnit
/usr/local/arm-linux-gnueabihf/lib
/usr/local/arm-linux-gnueabihf/share/CUnit
Obviously, if i don't specify a prefix for configure, each platform build overwrites the prev one which is no good
to then successfully link to these platform specific libs i need to specify the relevant lib dir for each target in its own LDFLAGS in the Makefile
Is this the right approach? Have I got the dir structure/location right for this sort of cross-build stuff? I assume there must be a defacto approach but not sure what it is..
possibly configure is supposed to handle all this stuff for me? maybe I just have to set --target correctly and perhaps --enable-multilib? all with --prefix=/usr/local?
some of the error msgs i get suggest /usr/lib/gcc-cross might be involve?
From reading more about cross compilation and the Gnu configure and build system it seems that I should just be setting the --target option for the configure step
but how do you know what the target names are? are they some fragment of the cross compiler names?
The 3 cross compilers I am using are:
arm-linux-gnueabihf-gcc-4.8
i686-w64-mingw32-gcc
x86_64-w64-mingw32-gcc
allowing me to cross-compile for ARM, win32 and win64
my host is 32 bit ubuntu, which I think might be --host i386-linux, but it seems that configure should get this right as its default
This is the procedure I finally figured out and got to work:
for each of my 3 cross-build tools (arm, win32, win64) my calls to configure looked like:
./configure --host=arm-linux-gnueabihf --build=i686-pc-linux-gnu --prefix=/usr/local/arm-linux-gnueabihf
./configure --host=i686-w64-mingw32 --build=i686-pc-linux-gnu --prefix=/usr/local/i686-w64-mingw32
./configure --host=x86_64-w64-mingw32 --build=i686-pc-linux-gnu --prefix=/usr/local/x86_64-w64-mingw32
each of these was followed by make, sudo make install
prior to calling configure for the arm cross build i had to do:
ln -s /usr/bin/arm-linux-gnueabihf-gcc-4.8 /usr/bin/arm-linux-gnueabihf-gcc
this was because the compiler had -4.8 tagged on the end so configure could not correctly 'guess' the name of the compiler
this issue did not apply to either the win32 or win64 mingw compilers
Note an additional gotcha was that when subsequently trying to link to these cross compiled CUnit libs, none of the cross compilers seemed to look in /usr/local/include by default so I had to manually add:
-I/usr/local/include
for each object file build
e.g. i added /usr/local/include to INCLUDE_DIRS in my Makefile
all this finally seems to have given me correctly cross built CUnit libs and I have successfully linked to them to produce cross built unit test binaries for each of the target platforms.
not at all easy and I would venture to call the configure option settings 'counter-intuitive' - as ever it is worth taking the time to read the relevant docs - this snippet was pertinent:
There are three system names that the build knows about: the machine
you are building on (build), the machine that you are building for
(host), and the machine that GCC will produce code for (target). When
you configure GCC, you specify these with --build=, --host=, and
--target=.
Specifying the host without specifying the build should be avoided, as
configure may (and once did) assume that the host you specify is also
the build, which may not be true.
If build, host, and target are all the same, this is called a native.
If build and host are the same but target is different, this is called
a cross. If build, host, and target are all different this is called a
canadian (for obscure reasons dealing with Canada's political party
and the background of the person working on the build at that time).
If host and target are the same, but build is different, you are using
a cross-compiler to build a native for a different system. Some people
call this a host-x-host, crossed native, or cross-built native.
and also:
When people configure a project like './configure', man often meets
these three confusing options, which are more related with
cross-compilation
--host: In which system the generated program will run.
--build: In which system the program will be built.
--target: this option is only used to build a cross-compiling
toolchain. When the tool chain generates executable program, in which target
system the program will run.
An example of tslib (a mouse driver library)
'./configure --host=arm-linux --build=i686-pc-linux-gnu': the
dynamically library is built on a x86 linux computer but will be used
for a embedded arm linux system.
I'm trying to cross-compile the OpenCV library for using it on an embedded system running Montavista Linux(the system has an ARM926 processor). I've managed to configure and generate the makefiles; the sources are built OK, including the 3rd party libraries. The trouble comes at link time. For some reason libtool picks some libraries from the host system (libjpeg, libtiff, libpng) and tries to link them against the ARM9 object files(which evidently is wrong). The error I get is
/usr/lib/libpng12.so: could not read symbols: File in wrong format.
I couldn't and I still can't figure out what exactly is wrong with my setup(I even tried to build the library directly on the ARM9 system but unfortunately it has a very small amount of RAM and gcc chokes). I also modified the LD_LIBRARY_PATH envvar to contain the target's system libraries and exported it before running configure and make.
Below is what I pass to configure:
LDFLAGS="-L/opt/Montavista/pro/devkit/arm/v5t_le/target/usr/lib" CFLAGS="-I/opt
/Montavista/pro/devkit/arm/v5t_le/target/usr/include -fsigned-char -march=armv5te
-mtune=arm926ej-s -ffast-math -fomit-frame-pointer -funroll-loops" CC=/opt/Montavista
/pro/devkit/arm/v5t_le/bin/arm_v5t_le-gcc CXXFLAGS="-fsigned-char -march=armv5te
-mtune=arm926ej-s -ffast-math -fomit-frame-pointer -funroll-loops" CXX=/opt/Montavista
/pro/devkit/arm/v5t_le/bin/arm_v5t_le-g++ ./configure --host=armv5tl-montavista-linux-
gnueabi --without-gtk --without-v4l --without-carbon --without-quicktime --without-
1394libs --without-ffmpeg --without-imageio --without-python --without-swig --enable-
static --enable-shared --disable-apps --prefix=/home/dev/Development/lib
I found this question on SO but unfortunately it does not provide a solution for me.
I'm using gcc version 4.2.0 (MontaVista 4.2.0-16.0.32.0801914 2008-08-30) on Montavista Linux for ARM(Leopard board powered by a TI DM365), OpenCV 2.0.0. My host system is Ubuntu 10.4.
Any pointers on how to tackle this issue would be of very much help.
Thanks
[UPDATE][SOLVED]: The autotools based method of generating the makefiles for OpenCV 2.0.0 seems to be broken when trying cross-compiling(or for some odd reason it did not work for me). I used the CMake GUI and specified a proper toolchain.cmake file and everything went smooth. See the answer below.
Procedure for cross-compiling OpenCV 2.0 for ARM using CMake GUI
Requirements
OpenCV 2.0 source tarball
CodeSourcery ARM cross-compiler v2009q1 or v2010.09(both tested)
Ubuntu 10.10/11.04 host machine
CMake >= v2.6 with CMake GUI
Steps
Unpack somewhere on your host machine the OpenCV tarball; cd to that location and create a build directory
Open the CMake GUI. Select:
Where is the source code:==path to the folder you unpacked the OpenCV tarball
Where to build the binaries:==path to the build folder you created in the first step
Add a new entry named COMPILER_ROOT as a path entry and set its value to the path of your cross compiler e.g. /opt/CodeSourcery/Sourcery_G++_Lite/bin
Set CMAKE_TOOLCHAIN_FILE to the path of your toolchain file on your host machine; example toolchain.cmake:
# this one is important
SET(CMAKE_SYSTEM_NAME Linux)
#this one not so much
SET(CMAKE_SYSTEM_VERSION 1)
# specify the cross compiler
set(COMPILER_ROOT /opt/CodeSourcery/Sourcery_G++_Lite/bin)
set(CMAKE_C_COMPILER ${COMPILER_ROOT}/arm-none-linux-gnueabi-gcc)
set(CMAKE_CXX_COMPILER ${COMPILER_ROOT}/arm-none-linux-gnueabi-g++)
# specify how to set the CMake compilation flags
# CPP
SET(CMAKE_CXX_FLAGS $ENV{CXX_FLAGS} CACHE FORCE "")
SET(CMAKE_CXX_FLAGS_DEBUG $ENV{CXX_FLAGS_DEBUG} CACHE FORCE "")
SET(CMAKE_CXX_FLAGS_RELEASE $ENV{CXX_FLAGS_RELEASE} CACHE FORCE "")
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO $ENV{CXX_FLAGS_RELWITHDEBINFO} CACHE FORCE "")
SET(CMAKE_CXX_LINK_FLAGS $ENV{CMAKE_EXE_LINKER_FLAGS} CACHE FORCE "")
SET(CMAKE_C_LINK_FLAGS $ENV{CMAKE_EXE_LINKER_FLAGS} CACHE FORCE "")
SET(CMAKE_CXX_LINK_FLAGS_RELEASE $ENV{CMAKE_EXE_LINKER_FLAGS} CACHE FORCE "")
SET(CMAKE_CXX_LINK_FLAGS_DEBUG $ENV{CMAKE_EXE_LINKER_FLAGS} CACHE FORCE "")
# C
#SET(CMAKE_C_FLAGS $ENV{C_FLAGS} CACHE FORCE "")
SET(CMAKE_C_FLAGS_DEBUG $ENV{C_FLAGS_DEBUG} CACHE FORCE "")
SET(CMAKE_C_FLAGS_RELEASE $ENV{C_FLAGS_RELEASE} CACHE FORCE "")
SET(CMAKE_C_FLAGS_RELWITHDEBINFO $ENV{C_FLAGS_RELWITHDEBINFO} CACHE FORCE "")
# where is the target environment
SET(CMAKE_FIND_ROOT_PATH ${COMPILER_ROOT})
# search for programs in the build host directories
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# for libraries and headers in the target directories
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
Tweak other settings to your needs e.g.EXECUTABLE_OUTPUT_PATH LIBRARY_OUTPUT_PATH CMAKE_BUILD_TYPE CMAKE_CFLAGS_DEBUG CMAKE_CFLAGS_RELEASE, third party libraries you want to build with etc.
Press Configure then Generate; check for eventual errors(everything should run smoothly but you never know)
If everything went OK in the generation phase then cd to the build folder, type make then sit back and relax until the build process is done
It seems you are using an old version of OpenCv since it still uses the .configure mechanism. This is good in a sense, because CMake is not known to be cross-compilation friendly.
LDFLAGS="-L/opt/Montavista/pro/devkit/arm/v5t_le/target/usr/lib"
This is were the linker will look for libraries. It should be enough. Are you sure the libraries needed by OpenCV are in this PATH ?
A first Hack would be to rename the libraries in /usr/lib, so that the linker don't find them, and see if it find the target libraries. This is ugly, maybe more than ugly. Don't do it. Yet.
A second solution is to do native compilation. But it an emulated ARM box, not on real, slow and memory poor hardware. I have no experience either with this kind of cross-compile method, but here is a link to get you started.
EDIT
Wait !!, Which version of OpenCV are you using ? I thought OpenCV was not using .configure et al. ? There is probably a more elegant solution using .configure flags. Or maybe non optionnal libraries are somehow hardcoded.
Interestingly I'm currently trying to get version 2.1.0 to build for ARM. It relies on cmake which is a real pain to try to get ready for cross-compiling. There's no way to specify what toolchain to use, I have to spot the variable names for all binutils, hoping not to forget any. There are still a bunch of magically defined variables that prevent it from building, I'm giving up right now. I'm still seeing some -march=i686 magically appended and some libs referenced from my build system. What a mess !
Maybe when I have time I'll try to downgrade to an older version making use of more standard tools, but cmake clearly complicates the situation here.