1

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!

Zandorath
  • 13
  • 4

1 Answers1

1

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)
Fraser
  • 74,704
  • 20
  • 238
  • 215
  • First I'd like to thank you for your help! Theres only one thing I dont understand, what sources do I need to initialize besides the headers? – Zandorath Jan 19 '13 at 18:24
  • If you're not building libnet as part of your own project (option 1 above) then it's just the libnet headers you need. You only need the libnet sources if you're building it as part of your own project, in which case you'll need *all* the libnet headers and sources. You probably just need to make a list of all the libnet files and do `add_library` - but looking through the existing libnet makefiles will let you see if any files need excluded / special handling / etc. – Fraser Jan 21 '13 at 08:02
  • Sorry for answering this late, but I never used the set() command before. What does the Syntax look like? I couldnt find a documentation showing how to reference the adress of the files. – Zandorath Jan 28 '13 at 17:52
  • The syntax for [`set`](http://www.cmake.org/cmake/help/v2.8.10/cmake.html#command:set) is `set( ... )` (i.e. a space-separated list). In this case, `value1` to `valueN` are simply paths to files. The paths can be relative to your CMakeLists.txt, should ideally use forward slashes `/` as the path separators, and if the paths contain spaces each one needs to be wrapped in quotes. e.g. `set(LibnetSources libnet/dir1/file1.cpp libnet/dir1/file1.h libnet/dir1/file2.cpp etc.)` – Fraser Jan 28 '13 at 21:03
  • Note that you don't need to use the `set` command if you choose to use `file(GLOB...)` instead (as per my last paragraph in the answer). – Fraser Jan 28 '13 at 21:04
  • Thanks for your help I now understood how to use the set() command. While creating the collection of files I encountered files of the type .h.in and I could not find out how to treat these, but the usual way does not work. Sorry but I am a newbie to cmake and I never heard of .h.in and couldnt find any documentation about these headers. – Zandorath Jan 29 '13 at 20:13
  • Often these files are used as inputs for the CMake command [`configure_file`](http://www.cmake.org/cmake/help/v2.8.10/cmake.html#command:configure_file) – Fraser Jan 30 '13 at 02:32
  • I encounter all sorts of problems concerning the sourcefiles. Most of them cant be compiled because they use macros and adresses defined in the makefiles. I dont think it will be possible to get this to work without writing a whole bunch of new makefiles for cmake. Is there another possibility to use libnet with kdevelop then cmake? I am used to Visual Studio on Windows where I never had to create any makefiles and the code I would like to write on Linux now does not have to be CrossPlatform Code. – Zandorath Jan 30 '13 at 16:30
  • Why cant the existing makefiles the library uses be used by cmake? Is there a possibility to configure the existing makefiles in a way that cmake can use them? I dont see any other possibility to get libnet to work, because I am new to cmake I dint think I am able to rewrite all those makefiles in cmake :( – Zandorath Feb 02 '13 at 12:47
  • It sounds like your best option is to just build and install libnet as per its own instructions rather than trying to modify it to use CMake. – Fraser Feb 02 '13 at 14:08
  • OK - I just added details of a better option. This works for me on Ubuntu using gcc. – Fraser Feb 02 '13 at 15:58
  • I hope I am not annoying you, but I am afraid I dont know how to build a library using make. – Zandorath Feb 02 '13 at 16:34
  • No problem :-) You're on Linux - right? With the last option I just put up, if you just open the CMakeLists.txt in KDevelop as a new project (I'm not really familiar with that IDE) and run configure then build, it should just work. – Fraser Feb 02 '13 at 16:53
  • I am using CMake Version 2.8.1, on the internet I found this method of updating CMake: `apt-get remove cmake` and then install the latest version. Is this correct or might this cause problems with kdevelop? – Zandorath Feb 03 '13 at 14:22
  • Sorry for spaming you this often, but now having installed cmake 2.8.10.2 it get this build error: `make *** [cmake_check_build_system] Error 1` Is it possible that this error occurs because the downloaded file is encrypted? – Zandorath Feb 04 '13 at 15:13
  • I think this is now at the point of needing a new question :-) I tested the 3rd option I gave on Ubuntu (albeit using CMake and gcc via the command line rather than through kdevelop). I'd recommend trying this from scratch (delete your build directories and start over) and if there's still an issue, give the exact steps to produce the error and also the full error message. – Fraser Feb 04 '13 at 20:24
  • Thanks a lot for your help! Everything now works fine. I used the `ExternelProject_Add()` after having cleaned up everything and I have to say, that I would never have been able to get this to work without your help! – Zandorath Feb 05 '13 at 20:39
  • Cool :-) Glad you got there! – Fraser Feb 05 '13 at 20:41