I am confused on how to statically include the source code of SDL2. I am trying to do this to make a library I am working on more portable.
When I was setting this up as executable the library was compiled with it fine, but when I changed it to a library it wouldn't include the library.
Currently, when I try to include my library in another project it says "Cannot open include file: 'SDL2/SDL.h': No such file or directory". So it leads me to think that the cause of the error is that the include directories aren't exported with the static library.
My Filesystem:
include
--Header Files
src
--Source Files
extern
--SDL2
build
Here is an example of the file causing the error:
#include <iostream>
#include <SDL.h> //Error
using namespace std;
/* The code */
Here is an example of my main CMakeLists.txt:
cmake_minimum_required(VERSION 3.7)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
project(MyProject VERSION 1.0.0)
set(SDL2_SOURCE_DIR “${CMAKE_SOURCE_DIR}/extern/SDL2”)
add_subdirectory(extern/SDL2)
add_subdirectory(src)
Here is an example of my src CMakeLists.txt:
set(PROJECT_NAME MyProject)
file(GLOB HEADER_FILES "${CMAKE_SOURCE_DIR}/include/*.h")
file(GLOB SOURCES "*.cpp")
add_library(${PROJECT_NAME} ${SOURCES} ${HEADER_FILES})
target_include_directories(${PROJECT_NAME} PUBLIC "${CMAKE_SOURCE_DIR}/include" PUBLIC "${CMAKE_SOURCE_DIR}/extern/SDL2/include")
target_link_libraries(${PROJECT_NAME} PRIVATE SDL2main SDL2-static)
set_target_properties( ${PROJECT_NAME}
PROPERTIES
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/lib"
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/lib"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin"
)
From sdl2 CMakeLists.txt try:
set(SDL_STATIC 1)
add_subdirectory(extern/SDL2) # And I recommend EXCLUDE_FROM_ALL
Also to be sure add a check:
foreach(i IN ITEMS SDL2main SDL2-static)
if(NOT TARGET ${i})
message(FATAL_ERROR "${i} is not a target")
endif()
endif()
target_link_libraries(${PROJECT_NAME} PRIVATE SDL2main SDL2-static)
Related
I am trying to create a library on the top of SDL2. For the compilation I'm using cmake.
First I had this CMakeLists.txt for the library :
cmake_minimum_required(VERSION 3.10)
project(SquareEngine)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/")
find_package(SDL2 REQUIRED)
find_package(SDL2_image REQUIRED)
include_directories(${SDL2_INCLUDE_DIRS})
include_directories(${SDL2_IMAGE_INCLUDE_DIRS})
set (SRCS Main.cpp
Rectangle.cpp
Scene.cpp
SquareEngine.cpp)
set (HEADERS Rectangle.hpp
Scene.hpp
SquareEngine.hpp
utils/Color.hpp
utils/Vector.hpp)
add_library(SquareEngine ${SRCS} ${HEADERS} ${SDL} ${SDL_SRC})
target_link_libraries(SquareEngine ${SDL2_LIBRARIES} ${SDL2_IMAGE_LIBRARIES})
To include the SDL2 and SDL2 image I follow this instructions.
When I try to build it's work perfectly.
Now I try to use my library in a project. I create my own project and I link my librairy that is located in a subfolder /SquareEngine in my project. For the project I use this CMakeLists.txt :
cmake_minimum_required(VERSION 3.10)
project(Demo)
set (SRCS Main.cpp)
add_subdirectory(SquareEngine)
add_executable(Demo ${SRCS})
target_link_libraries(Demo PUBLIC SquareEngine)
target_include_directories(Demo PUBLIC SquareEngine)
When I try to build the project I got an error like this :
Cannot open include file: 'SDL.h': No such file or directory
I try to figure out for long time and I don't have any clue why.
Maybe it will be better to use the SDL in static rather than shared ?
I think you need to add the SDL include dirs to the SquareEngine library:
target_include_directories(SquareEngine PUBLIC ${SDL2_INCLUDE_DIRS} ${SDL2_IMAGE_INCLUDE_DIRS})
The most recent SDL2 releases provide SDL2::* CMake targets such that you don't need to fiddle with CMake variables anymore.
So there's no more need to ship your custom FindSDL2.cmake and/or FindSDL2_image.cmake modules.
With those, you can rewrite your cmake script as:
cmake_minimum_required(VERSION 3.10)
project(SquareEngine)
find_package(SDL2 REQUIRED CONFIG)
find_package(SDL2_image REQUIRED CONFIG)
set (SRCS
Main.cpp
Rectangle.cpp
Scene.cpp
SquareEngine.cpp
)
set (HEADERS
Rectangle.hpp
Scene.hpp
SquareEngine.hpp
utils/Color.hpp
utils/Vector.hpp
)
add_library(SquareEngine ${SRCS} ${HEADERS})
target_link_libraries(SquareEngine PRIVATE SDL2::SDL2 SDL2_image::SDL2_image)
target_include_directories(SquareEngine
PUBLIC
$<TARGET_PROPERTY:SDL2::SDL2,INTERFACE_INCLUDE_DIRECTORIES>
$<TARGET_PROPERTY:SDL2_image::SDL2_image,INTERFACE_INCLUDE_DIRECTORIES>
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>"
)
It can then be used in your game as:
cmake_minimum_required(VERSION 3.10)
project(Demo)
set (SRCS Main.cpp)
add_subdirectory(SquareEngine)
add_executable(Demo ${SRCS})
target_link_libraries(Demo PUBLIC SquareEngine)
I followed the asssimp library's installation guide, which used Visual Studio and did all the necessary steps to include it in the project through the GUI when I did everything through pure CMake and MinGW.
I need to include headers and two library files in my project: assimp-[...].dll and assimp-[...].lib
My assimp proj hierarchy
I started to figure out how to write my own CMakeLists.txt and came up with this:
cmake_minimum_required(VERSION 3.2 FATAL_ERROR)
project(Assimp)
add_library(assimp SHARED IMPORTED GLOBAL)
file(GLOB_RECURSE ROOT_SOURCE "./assimp/*.cpp")
file(GLOB_RECURSE ROOT_INLINE "./assimp/*.inl")
file(GLOB_RECURSE ROOT_HPP "./assimp/*.hpp")
file(GLOB_RECURSE ROOT_HEADER "./assimp/*.h")
file(GLOB_RECURSE COMPILER_HEADER "./assimp/Compiler/*.h")
file(GLOB_RECURSE PORT_HEADER "./assimp/port/AndroidJNI/*.h")
source_group("Compiler Files" FILES ${COMPILER_HEADER})
source_group("Port Files" FILES ${PORT_HEADER})
include(GNUInstallDirs)
if(BUILD_STATIC_LIBS)
add_library(assimp_static STATIC
${ROOT_SOURCE} ${ROOT_INLINE} ${ROOT_HPP}
${ROOT_HEADER} ${COMPILER_HEADER} ${PORT_HEADER}
)
target_link_libraries(assimp_static PUBLIC assimp)
add_library(assimp::assimp_static ALIAS assimp_static)
endif()
if(BUILD_SHARED_LIBS)
add_library(assimp_shared SHARED
${ROOT_SOURCE} ${ROOT_INLINE} ${ROOT_HPP}
${ROOT_HEADER} ${COMPILER_HEADER} ${PORT_HEADER}
)
target_link_libraries(assimp_shared PUBLIC assimp)
add_library(assimp::assimp_shared ALIAS assimp_shared)
endif()
set_property(TARGET assimp PROPERTY IMPORTED_LOCATION "${PROJECT_SOURCE_DIR}/external/assimp/lib/assimp-vc143-mtd.dll")
set_property(TARGET assimp PROPERTY IMPORTED_IMPLIB "${PROJECT_SOURCE_DIR}/external/assimp/lib/assimp-vc143-mtd.lib")
After that I'm linking it in the main CMakeLists.txt:
add_executable(${PROJECT_NAME} [src code files here])
add_subdirectory(external/assimp)
target_link_libraries(${PROJECT_NAME} PRIVATE assimp)
But after that, I can't see any header from this library, as well as its directory, and I'm not even sure if the dynamic libraries from the "lib" folder are included correctly.
What am I doing wrong?
I have a simple project, which consists of several directories with sources and CMakeLists.txt files.
Here is my project structure:
CMakeLists.txt\
main.c
src/source1.c\
src/source1.h\
src/CMakeLists.txt
test/test.cpp\
test/main.cpp\
test/CMakeLists.txt
googletest
Main executable has been built successfully, but test executable not, linker errors instead (undefined references to functions from src directory). Here is my CMake files content:
CMakeLists.txt:
cmake_minimum_required(VERSION 3.22)
project(TIC-TAC-TOE)
set(CMAKE_C_STANDARD 99)
set(CXXMAKE_C_STANDARD 11)
set(POSITION_INDEPENDENT_CODE ON)
enable_testing()
include_directories(src)
add_subdirectory(test)
add_subdirectory(src)
add_subdirectory(googletest)
add_executable(TIC-TAC-TOE main.c)
target_link_libraries(TIC-TAC-TOE tic_tac_toe-lib)
src/CMakeLists.txt:
set(Sources tic-tac-toe.c tic-tac-toe.h)
add_library(tic_tac_toe-lib STATIC ${Sources})
test/CMakeLists.txt:
project(TIC-TAC-TOE-TEST)
set(Sources tic-tac-toe-test.cpp
main.cpp
)
add_executable(TIC-TAC-TOE-TEST ${Sources})
add_test(
NAME TIC-TAC-TOE-TEST
COMMAND TIC-TAC-TOE-TEST
)
target_link_libraries(TIC-TAC-TOE-TEST PUBLIC tic_tac_toe-lib gtest_main)
I am confused on how to statically include the source code of SDL2. I am trying to do this to make a library I am working on more portable.
Currently, when I try to include my library in another project it says "Cannot open include file: 'SDL2/SDL.h': No such file or directory".
My Filesystem:
include
--Header Files
src
--Source Files
extern
--SDL2
build
Here is an example of the file causing the error:
#include <iostream>
#include <SDL2/SDL.h> //Error
using namespace std;
/* The code */
Here is an example of my main CMakeLists.txt:
cmake_minimum_required(VERSION 3.7)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
project(MyProject VERSION 1.0.0)
set(SDL2_SOURCE_DIR “${CMAKE_SOURCE_DIR}/extern/SDL2”)
add_subdirectory(extern/SDL2)
add_subdirectory(src)
Here is an example of my src CMakeLists.txt:
set(PROJECT_NAME MyProject)
file(GLOB HEADER_FILES "${CMAKE_SOURCE_DIR}/include/*.h")
file(GLOB SOURCES "*.cpp")
add_library(${PROJECT_NAME} ${SOURCES} ${HEADER_FILES})
target_include_directories(${PROJECT_NAME} PUBLIC "${CMAKE_SOURCE_DIR}/include")
target_link_libraries(${PROJECT_NAME} PRIVATE SDL2main SDL2-static)
set_target_properties( ${PROJECT_NAME}
PROPERTIES
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/lib"
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/lib"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin"
)
add_subdirectory() will process the subdirectory as a cmake porject (process the provided CMakeLists.txt for SDL). If you read that CMakeLists.txt, you'd see that it add the include directories relative to SDL2_SOURCE_DIR, which is empty by default.
What I would try is to set SDL2_SOURCE_DIR to ${CMAKE_CURRENT_SOURCE_DIR}/extern/SDL2 to make the path absolute. Like that SDL include dirs will be valid everywhere in your project.
You can also manually add the correct includes by using the include_directories() directive.
I have a custom library which exports include/, lib/ and lib/cmake/ which contains MyProjectConfig.cmake with the following contents:
set(MyProject_INCLUDE_DIRS "/home/.../cmake-build-debug/thirdparty/myproj/include")
set(MyProject_LIBRARY_DIRS "/home/.../cmake-build-debug/thirdparty/myproj/lib")
set(MyProject_LIBRARIES "MyProject")
message(STATUS "MyProject found. Headers: ${MyProject_INCLUDE_DIRS}")
I use it in another project like this:
include(ExternalProject)
ExternalProject_Add(MyProjectExternal
PREFIX "${CMAKE_BINARY_DIR}/external/myproject"
GIT_REPOSITORY "git#bitbucket.org:myproject.git"
GIT_TAG "master"
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/thirdparty/myproject
)
add_dependencies(${PROJECT_NAME} MyProjectExternal)
# prevent error on first project use when dir doesn't exist
if(EXISTS ${CMAKE_BINARY_DIR}/thirdparty/myproject/lib)
find_package(MyProject REQUIRED HINTS ${CMAKE_BINARY_DIR}/thirdparty/myproject/lib/cmake)
find_library(MyProject_LIB MyProject HINTS ${MyProject_LIBRARY_DIRS})
target_link_libraries(${PROJECT_NAME} PUBLIC ${MyProject_LIB})
target_include_directories(${PROJECT_NAME} PRIVATE ${MyProject_INCLUDE_DIRS})
endif()
I expected that the variables set in MyProjectConfig.cmake would be picked up automatically by cmake to find the library by name and this would work:
find_package(MyProject REQUIRED HINTS ${CMAKE_BINARY_DIR}/thirdparty/myproject/lib/cmake)
target_link_libraries(${PROJECT_NAME} PUBLIC MyProject)
But it doesn't:
[ 87%] Built target MyProjectExternal
[ 90%] Linking CXX executable RootProject
/usr/bin/ld: cannot find -lMyProject
collect2: error: ld returned 1 exit status
Part II (as requested here) The full code and the steps to reproduce the problem
Library Code (mylib branch)
CMakeLists.txt
cmake_minimum_required(VERSION 3.8)
project(MyLib VERSION 1.0.0 LANGUAGES CXX)
add_library(${PROJECT_NAME} SHARED
src/mylib/hello.cpp
)
target_include_directories(${PROJECT_NAME}
PUBLIC $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/include> $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
set_target_properties(${PROJECT_NAME} PROPERTIES
CXX_STANDARD 11
CXX_STANDARD_REQUIRED YES
CXX_EXTENSIONS NO
)
include(cmake/install.cmake)
cmake/install.cmake
include(GNUInstallDirs)
install(TARGETS ${PROJECT_NAME} EXPORT ${PROJECT_NAME}Targets
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)
install(DIRECTORY ${CMAKE_SOURCE_DIR}/include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
include(GenerateExportHeader)
generate_export_header(${PROJECT_NAME}
EXPORT_MACRO_NAME EXPORT
NO_EXPORT_MACRO_NAME NO_EXPORT
PREFIX_NAME MYLIB_
EXPORT_FILE_NAME ${CMAKE_BINARY_DIR}/include-exports/mylib/export.h)
target_include_directories(${PROJECT_NAME}
PUBLIC
$<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/include-exports>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
install(DIRECTORY ${CMAKE_BINARY_DIR}/include-exports/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
include(CMakePackageConfigHelpers)
set_property(TARGET ${PROJECT_NAME} PROPERTY VERSION ${PROJECT_VERSION})
set_property(TARGET ${PROJECT_NAME} PROPERTY SOVERSION ${PROJECT_VERSION_MAJOR})
set_property(TARGET ${PROJECT_NAME} PROPERTY INTERFACE_${PROJECT_NAME}_MAJOR_VERSION ${PROJECT_VERSION_MAJOR})
set_property(TARGET ${PROJECT_NAME} APPEND PROPERTY COMPATIBLE_INTERFACE_STRING ${PROJECT_VERSION_MAJOR})
write_basic_package_version_file(
"${CMAKE_BINARY_DIR}/CMakePackage/${PROJECT_NAME}ConfigVersion.cmake"
VERSION ${PROJECT_VERSION}
COMPATIBILITY SameMajorVersion
)
export(EXPORT ${PROJECT_NAME}Targets
FILE "${CMAKE_BINARY_DIR}/CMakePackage/${PROJECT_NAME}.cmake"
)
SET(CONFIG_SOURCE_DIR ${CMAKE_SOURCE_DIR})
SET(CONFIG_DIR ${CMAKE_BINARY_DIR})
SET(${PROJECT_NAME}_INCLUDE_DIR "\${${PROJECT_NAME}_SOURCE_DIR}/include")
configure_package_config_file(${CMAKE_SOURCE_DIR}/cmake/Config.cmake.in
"${CMAKE_BINARY_DIR}/CMakePackage/${PROJECT_NAME}Config.cmake"
INSTALL_DESTINATION lib/cmake/${PROJECT_NAME}
PATH_VARS ${PROJECT_NAME}_INCLUDE_DIR)
install(EXPORT ${PROJECT_NAME}Targets
FILE ${PROJECT_NAME}.cmake
DESTINATION lib/cmake/${PROJECT_NAME}
)
install(
FILES
"${CMAKE_BINARY_DIR}/CMakePackage/${PROJECT_NAME}Config.cmake"
"${CMAKE_BINARY_DIR}/CMakePackage/${PROJECT_NAME}ConfigVersion.cmake"
DESTINATION lib/cmake/${PROJECT_NAME}
COMPONENT Devel
)
cmake/Config.cmake.in
#PACKAGE_INIT#
set_and_check(#PROJECT_NAME#_INCLUDE_DIRS "#CMAKE_INSTALL_PREFIX#/#CMAKE_INSTALL_INCLUDEDIR#")
set_and_check(#PROJECT_NAME#_LIBRARY_DIRS "#CMAKE_INSTALL_PREFIX#/#CMAKE_INSTALL_LIBDIR#")
set(#PROJECT_NAME#_LIBRARIES "#PROJECT_NAME#")
check_required_components(#PROJECT_NAME#)
message(STATUS "#PROJECT_NAME# found. Headers: ${#PROJECT_NAME#_INCLUDE_DIRS}")
include/mylib/hello.h
#ifndef MYLIB_HELLO_H
#define MYLIB_HELLO_H
#include <mylib/export.h>
namespace mylib {
extern MYLIB_EXPORT void hello();
}
#endif
src/mylib/hello.cpp
#include <mylib/hello.h>
#include <iostream>
namespace mylib {
void hello() {
std::cout << "Hello, MyLib!" << std::endl;
}
}
Application Code (master branch)
CMakeLists.txt
cmake_minimum_required(VERSION 3.8)
project(MyLibConsumer VERSION 1.0.0 LANGUAGES CXX)
add_executable(${PROJECT_NAME}
main.cpp)
set_target_properties(${PROJECT_NAME} PROPERTIES
CXX_STANDARD 11
CXX_STANDARD_REQUIRED YES
CXX_EXTENSIONS NO
)
include(ExternalProject)
set(LIB_INSTALL_DIR ${CMAKE_BINARY_DIR}/thirdparty/mylib)
ExternalProject_Add(MyLibExternal
PREFIX "${CMAKE_BINARY_DIR}/external/mylib"
GIT_REPOSITORY "https://github.com/arteniioleg/stackoverflow-question-46772541.git"
GIT_TAG "mylib"
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIB_INSTALL_DIR}
)
add_dependencies(${PROJECT_NAME} MyLibExternal)
if(EXISTS ${LIB_INSTALL_DIR}/lib) # prevent error on first cmake load
find_package(MyLib REQUIRED HINTS ${LIB_INSTALL_DIR}/lib/cmake)
# fixme: make this work
target_link_libraries(${PROJECT_NAME} PUBLIC MyLib)
# to test: comment the above line and uncomment the below lines
#find_library(MyLib_LIB MyLib HINTS ${MyLib_LIBRARY_DIRS})
#target_link_libraries(${PROJECT_NAME} PRIVATE ${MyLib_LIB})
#target_include_directories(${PROJECT_NAME} PRIVATE ${MyLib_INCLUDE_DIRS})
endif()
main.cpp
#include <mylib/hello.h>
int main()
{
mylib::hello();
return 0;
}
The Error
main.cpp:1:25: fatal error: mylib/hello.h: No such file or directory
#include <mylib/hello.h>
^
Using the MyLib_* variables created by find_package() fixes the problem but it's too verbose.
As suggested here:
However, recommended way is to use CMake functionality for create configuration file. Such way, fully-fledged target will be created, and can be used for linking.
How to do that?
I want to use my library in 2 steps, like Qt:
find_package(Qt5Widgets)
target_link_libraries(myApp Qt5::Widgets)
Just include MyProject.cmake in MyProjectConfig.cmake (it is not included by default)
include(${CMAKE_CURRENT_LIST_DIR}/MyProject.cmake)
The final version of key files:
LIBRARY/cmake/Config.cmake.in
Removed redundant variables: *_INCLUDE_DIRS, *_LIBRARY_DIRS, *_LIBRARIES
#PACKAGE_INIT#
include(${CMAKE_CURRENT_LIST_DIR}/#PROJECT_NAME#.cmake)
check_required_components(#PROJECT_NAME#)
message(STATUS "#PROJECT_NAME# found.")
EXECUTABLE/CMakeLists.txt
Moved external projects before executable and return() if external projects are not built.
cmake_minimum_required(VERSION 3.8)
project(MyLibConsumer VERSION 1.0.0 LANGUAGES CXX)
set(LIB_INSTALL_DIR ${CMAKE_BINARY_DIR}/thirdparty/mylib)
include(ExternalProject)
ExternalProject_Add(MyLibExternal
PREFIX "${CMAKE_BINARY_DIR}/external/mylib"
GIT_REPOSITORY "https://github.com/arteniioleg/stackoverflow-question-46772541.git"
GIT_TAG "mylib"
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIB_INSTALL_DIR}
)
if(NOT EXISTS ${LIB_INSTALL_DIR}/lib)
# Happens on first CMake run.
# Can't continue because the below `find_package(REQUIRED)` will fail.
# Build all external project targets then rerun CMake and build the project target.
message(AUTHOR_WARNING "Build all external projects then reload cmake.")
return()
endif()
add_executable(${PROJECT_NAME} main.cpp)
set_target_properties(${PROJECT_NAME} PROPERTIES
CXX_STANDARD 11
CXX_STANDARD_REQUIRED YES
CXX_EXTENSIONS NO
)
add_dependencies(${PROJECT_NAME} MyLibExternal)
find_package(MyLib REQUIRED HINTS ${LIB_INSTALL_DIR})
target_link_libraries(${PROJECT_NAME} PRIVATE MyLib)
I expected that the variables set in MyProjectConfig.cmake would be picked up automatically by cmake to find the library by name.
The most "magic" in find_package command is how it searches *Config.cmake script. After the script is found, it is simply executed in the context of the caller.
In you case, CMake sets variables MyProject_INCLUDE_DIRS, MyProject_LIBRARY_DIRS and MyProject_LIBRARIES. Nothing more. It doesn't create MyProject target and so.
If you want find_package() preparing linking with MyProject library, you need to write your MyProjectConfig.cmake script accordingly (e.g., call link_directories() from it).
However, recommended way is to use CMake functionality for create configuration file. Such way, fully-fledged target will be created, and can be used for linking. See cmake-packages documentation for more info.