Skip to content

Commit

Permalink
First version
Browse files Browse the repository at this point in the history
pablospe committed Jun 1, 2014
1 parent b3ccdbb commit cd4215f
Showing 15 changed files with 318 additions and 3 deletions.
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
# builds
build*/*

# kdevelop
*.kdev4

# Compiled Object files
*.slo
*.lo
14 changes: 14 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
cmake_minimum_required(VERSION 2.6)
project(Foo)

# Set variables
include(${CMAKE_SOURCE_DIR}/cmake/SetEnv.cmake)

# Library sources
add_subdirectory(${LIBRARY_FOLDER})

# Library examples
add_subdirectory(examples)

# Install targets
include(${CMAKE_SOURCE_DIR}/cmake/InstallConfig.cmake)
86 changes: 83 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,84 @@
foo-cmake-lib
=============
cmake-example-library
=====================

How to install a library with cmake
This is an example of how to install a library with CMake, and then use
`find_package()` command to find it.

The **advantage** of this example is that it is auto generated. It is only
needed to change the *project name*.

It is based on the these two examples:
* [How to create a ProjectConfig.cmake file (cmake.org)]
(http://www.cmake.org/Wiki/CMake/Tutorials/How_to_create_a_ProjectConfig.cmake_file)
* [How to install a library (kde.org)]
(https://projects.kde.org/projects/kde/kdeexamples/repository/revisions/master/show/buildsystem/HowToInstallALibrary)

### How to create a library from this example?

Follow these steps:

* Copy files in a new folder.

* Change project name in the top-level `CMakeLists.txt`.

* (Optionally) Set the variables: `LIBRARY_NAME` and `LIBRARY_FOLDER`.
Otherwise project name in lowercase will be used.

See `cmake/SetEnv.cmake` file to see the difference.

### How to compile?

Assume the following settings:

project(Foo)
...
set(LIBRARY_NAME foo) # generated automatically (in lowercase)
set(LIBRARY_FOLDER foo) # generated automatically (in lowercase)

Example of a local installation:

> mkdir build
> cd build
> cmake -DCMAKE_INSTALL_PREFIX=../installed ..
> make install

Installed files:

> tree ../installed

├── bin
│   └── bar
├── include
│   └── foo
│   ├── foo.h
│   └── version.h
└── lib
├── CMake
│   └── Foo
│   ├── FooConfig.cmake
│   ├── FooConfigVersion.cmake
│   ├── FooTargets.cmake
│   └── FooTargets-noconfig.cmake
└── libfoo.so

Unintall library:

> make uninstall

### How to use it (internally)?

See the [bar example](examples/).

### How to use it (in an external project)?

Once the library is installed, CMake will be able to find it using
`find_package()` command. For example:

cmake_minimum_required(VERSION 2.6)
project(Bar)

find_package(Foo REQUIRED)
include_directories(${FOO_INCLUDE_DIRS})

add_executable(bar bar.cpp)
target_link_libraries(bar ${FOO_LIBRARIES})
13 changes: 13 additions & 0 deletions cmake/Config.cmake.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# - Config file for '@PROJECT_NAME@' package
# It defines the following variables
# @PROJECT_NAME_UPPERCASE@_INCLUDE_DIRS - include directories
# @PROJECT_NAME_UPPERCASE@_LIBRARIES - libraries to link against

# Include directory
set(@PROJECT_NAME_UPPERCASE@_INCLUDE_DIRS "@INSTALL_INCLUDE_DIR@")

# Import the exported targets
include("@INSTALL_CMAKE_DIR@/@PROJECT_NAME@Targets.cmake")

# Set the expected library variable
set(@PROJECT_NAME_UPPERCASE@_LIBRARIES @LIBRARY_NAME@)
22 changes: 22 additions & 0 deletions cmake/ConfigVersion.cmake.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# FIND_PACKAGE() searches for a <package>Config.cmake file and an associated
# <package>Version.cmake file, which it loads to check the version number,
# when a version has been specified in the find_package() call,
# e.g. find_package(Foo 1.0.0).
#
# This file can be used with configure_file() to generate such a file for a
# project with very basic logic.
#
# It sets PACKAGE_VERSION_EXACT if the current version string and the requested
# version string are exactly the same and it sets PACKAGE_VERSION_COMPATIBLE
# if the current version is >= requested version.

set(PACKAGE_VERSION @PROJECT_VERSION@)

IF("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}")
set(PACKAGE_VERSION_COMPATIBLE FALSE)
else()
set(PACKAGE_VERSION_COMPATIBLE TRUE)
if("${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}")
set(PACKAGE_VERSION_EXACT TRUE)
endif()
endif()
25 changes: 25 additions & 0 deletions cmake/InstallConfig.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# This "exports" all targets which have been put into the export set
install(EXPORT ${PROJECT_EXPORT}
DESTINATION ${INSTALL_CMAKE_DIR}
FILE ${PROJECT_NAME}Targets.cmake)

# Create the <package>Config.cmake.in
configure_file(${CMAKE_SOURCE_DIR}/cmake/Config.cmake.in
"${PROJECT_CMAKE_FILES}/${PROJECT_NAME}Config.cmake" @ONLY)

# Create the <package>ConfigVersion.cmake.in
configure_file(${CMAKE_SOURCE_DIR}/cmake/ConfigVersion.cmake.in
"${PROJECT_CMAKE_FILES}/${PROJECT_NAME}ConfigVersion.cmake" @ONLY)

# Install <package>Config.cmake and <package>ConfigVersion.cmake files
install(FILES
"${PROJECT_CMAKE_FILES}/${PROJECT_NAME}Config.cmake"
"${PROJECT_CMAKE_FILES}/${PROJECT_NAME}ConfigVersion.cmake"
DESTINATION "${INSTALL_CMAKE_DIR}" COMPONENT dev)

# Uninstall targets
configure_file("${CMAKE_SOURCE_DIR}/cmake/Uninstall.cmake.in"
"${PROJECT_CMAKE_FILES}/Uninstall.cmake"
IMMEDIATE @ONLY)
add_custom_target(uninstall
COMMAND ${CMAKE_COMMAND} -P ${PROJECT_CMAKE_FILES}/Uninstall.cmake)
27 changes: 27 additions & 0 deletions cmake/LibraryConfig.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Select library type
option(BUILD_SHARED_LIBS "Build @PROJECT_NAME@ as a shared library." ON)
if(BUILD_SHARED_LIBS)
set(LIBRARY_TYPE SHARED)
else()
set(LIBRARY_TYPE STATIC)
endif()

# Target
add_library(${LIBRARY_NAME} ${LIBRARY_TYPE} ${SOURCES} ${HEADERS})

# Install library
install(TARGETS ${LIBRARY_NAME}
EXPORT ${PROJECT_EXPORT}
RUNTIME DESTINATION "${INSTALL_BIN_DIR}" COMPONENT bin
LIBRARY DESTINATION "${INSTALL_LIB_DIR}" COMPONENT shlib
ARCHIVE DESTINATION "${INSTALL_LIB_DIR}" COMPONENT stlib
COMPONENT dev)

# Create 'version.h'
configure_file(version.h.in
"${CMAKE_CURRENT_BINARY_DIR}/version.h" @ONLY)
set(HEADERS ${HEADERS} ${CMAKE_CURRENT_BINARY_DIR}/version.h)

# Install headers
install(FILES ${HEADERS}
DESTINATION "${INSTALL_INCLUDE_DIR}/${LIBRARY_FOLDER}" )
56 changes: 56 additions & 0 deletions cmake/SetEnv.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Set PROJECT_NAME_UPPERCASE and PROJECT_NAME_LOWERCASE variables
string(TOUPPER ${PROJECT_NAME} PROJECT_NAME_UPPERCASE)
string(TOLOWER ${PROJECT_NAME} PROJECT_NAME_LOWERCASE)

# Version variables
set(MAJOR_VERSION 0)
set(MINOR_VERSION 1)
set(PATCH_VERSION 0)
set(PROJECT_VERSION ${MAJOR_VERSION}.${MINOR_VERSION}.${PATCH_VERSION})

# Offer the user the choice of overriding the installation directories
set(INSTALL_LIB_DIR lib CACHE PATH "Installation directory for libraries")
set(INSTALL_BIN_DIR bin CACHE PATH "Installation directory for executables")
set(INSTALL_INCLUDE_DIR include CACHE PATH
"Installation directory for header files")
if(WIN32 AND NOT CYGWIN)
set(DEF_INSTALL_CMAKE_DIR CMake)
else()
set(DEF_INSTALL_CMAKE_DIR lib/CMake/${PROJECT_NAME})
endif()
set(INSTALL_CMAKE_DIR ${DEF_INSTALL_CMAKE_DIR} CACHE PATH
"Installation directory for CMake files")

# Make relative paths absolute (needed later on)
foreach(p LIB BIN INCLUDE CMAKE)
set(var INSTALL_${p}_DIR)
if(NOT IS_ABSOLUTE "${${var}}")
set(${var} "${CMAKE_INSTALL_PREFIX}/${${var}}")
endif()
endforeach()

# Set up include-directories
include_directories(
"${PROJECT_SOURCE_DIR}"
"${PROJECT_BINARY_DIR}")

# Library name (by default is the project name in lowercase)
# Example: libfoo.so
if(NOT LIBRARY_NAME)
set(LIBRARY_NAME ${PROJECT_NAME_LOWERCASE})
endif()

# Library folder name (by default is the project name in lowercase)
# Example: #include <foo/foo.h>
if(NOT LIBRARY_FOLDER)
set(LIBRARY_FOLDER ${PROJECT_NAME_LOWERCASE})
endif()

# The export set for all the targets
set(PROJECT_EXPORT ${PROJECT_NAME}EXPORT)

# Path of the CNake files generated
set(PROJECT_CMAKE_FILES ${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY})

# The RPATH to be used when installing
set(CMAKE_INSTALL_RPATH ${INSTALL_LIB_DIR})
21 changes: 21 additions & 0 deletions cmake/Uninstall.cmake.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Note: http://www.cmake.org/Wiki/CMake_FAQ#Can_I_do_.22make_uninstall.22_with_CMake.3F

if(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
message(FATAL_ERROR "Cannot find install manifest: @CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
endif()

file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
string(REGEX REPLACE "\n" ";" files "${files}")
foreach(file ${files})
message(STATUS "Uninstalling $ENV{DESTDIR}${file}")
if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
exec_program("@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
OUTPUT_VARIABLE rm_out
RETURN_VALUE rm_retval)
if(NOT "${rm_retval}" STREQUAL 0)
message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}")
endif()
else()
message(STATUS "File $ENV{DESTDIR}${file} does not exist.")
endif()
endforeach(file)
15 changes: 15 additions & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# (uncomment these lines for an external project)
#
# cmake_minimum_required(VERSION 2.6)
# project(Bar)
# find_package(Foo REQUIRED)
# include_directories(${FOO_INCLUDE_DIRS})

add_executable(bar bar.cpp)

target_link_libraries(bar ${LIBRARY_NAME})

install(TARGETS bar
# In order to export target, uncomment next line
# EXPORT ${PROJECT_EXPORT}
RUNTIME DESTINATION "${INSTALL_BIN_DIR}" COMPONENT bin)
6 changes: 6 additions & 0 deletions examples/bar.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#include "foo/foo.h"

int main(int argc, char *argv[]) {
foo();
return 0;
}
7 changes: 7 additions & 0 deletions foo/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Set SOURCES variable
file(GLOB SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)

# Set HEADERS variable
file(GLOB HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/*.h)

include(${CMAKE_SOURCE_DIR}/cmake/LibraryConfig.cmake)
6 changes: 6 additions & 0 deletions foo/foo.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#include "foo.h"
#include <stdio.h>

void foo(void) {
printf("This is foo version %s\n", FOO_VERSION);
}
8 changes: 8 additions & 0 deletions foo/foo.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#ifndef FOO_FOO_H
#define FOO_FOO_H

#include <foo/version.h>

void foo(void);

#endif
9 changes: 9 additions & 0 deletions foo/version.h.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#ifndef @PROJECT_NAME_UPPERCASE@_VERSION_
#define @PROJECT_NAME_UPPERCASE@_VERSION_

#define @PROJECT_NAME_UPPERCASE@_MAJOR_VERSION (@MAJOR_VERSION@)
#define @PROJECT_NAME_UPPERCASE@_MINOR_VERSION (@MINOR_VERSION@)
#define @PROJECT_NAME_UPPERCASE@_PATCH_VERSION (@PATCH_VERSION@)
#define @PROJECT_NAME_UPPERCASE@_VERSION "@PROJECT_VERSION@"

#endif // @PROJECT_NAME_UPPERCASE@_VERSION_

0 comments on commit cd4215f

Please sign in to comment.