Compiling a static executable with CMake
Asked Answered
C

2

47

for a project I need to create an executable that includes all the libraries that I used (opencv, cgal) in order to execute it on a computer that has not those libraries. Currently, this is my CMakeLists.txt (I use linux).

cmake_minimum_required(VERSION 2.8)
#set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Wall -O2")
project( labeling )
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
add_library(OpenCV STATIC IMPORTED)
add_library(CGAL STATIC IMPORTED COMPONENTS Core)
add_library(GMP STATIC IMPORTED)
find_package(OpenCV REQUIRED)
find_package(CGAL QUIET COMPONENTS Core )
find_library(GMP_LIBRARY gmp /usr/lib)

include(src)
include( ${CGAL_USE_FILE} )
include( CGAL_CreateSingleSourceCGALProgram )


set(EXECUTABLE_OUTPUT_PATH ../bin)
set(CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++")

include_directories( src )
include_directories( ${OpenCV_INCLUDE_DIRS} )

file(GLOB_RECURSE nei_SRC "src/*.cpp")
add_executable( nei_segmentation ${nei_SRC})
target_link_libraries( nei_segmentation ${OpenCV_LIBS} ${GMP_LIBRARY})

In such a way only GMP and some other c++ libraries are included in my executable. My question is: How can I create a makefile in order to automatically including all the libraries in a static manner and creating only a "big" executable that contains all the libraries? Can you help me?

Cornerstone answered 9/7, 2014 at 8:4 Comment(5)
You should not use file(GLOB ...) to collect source files it will not work correctly when you add new files. It's also very unclear what your problem is. The add_library(IMPORTED) calls are also not doing anything.Weatherford
I need to create an executable that includes all the libraries (opencv, cgal and all the common c++ libraries) in order to execute the executable in other computer where Opencv or CGAL or other C++ libraries are not installed.Cornerstone
First you need to make sure that all libraries you depend on are built statically. This is often not the case. After that you need to make sure that your find_package calls find those static libraries.Weatherford
Yes, I know this, my problem is: how to include the .a files.Cornerstone
Andrea, what is your question exactly? In your post, the only question is "Can you help me?". You should edit your post, and at least describe what are the issues with what your have tested so far.Archaeo
M
77

As global CMake settings, add these lines before add_executable, valid for gcc/clang:

set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
set(BUILD_SHARED_LIBS OFF)
set(CMAKE_EXE_LINKER_FLAGS "-static")

On Modern CMake (3.x+ - target_link_libraries doc), you can apply the flag to specific targets, in this way:

target_link_libraries(your_target_name -static)

If you're using MSVC, you have to set the compiler and linker flags:

set(CMAKE_FIND_LIBRARY_SUFFIXES ".lib")
target_compile_options(your_target_name [PUBLIC|PRIVATE] /MT)
target_link_options(your_target_name [PUBLIC|PRIVATE] /INCREMENTAL:NO /NODEFAULTLIB:MSVCRT)

or alternatively also:

set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")

and if you are using MFC, you need to specify the flag to 1 see here:

set(CMAKE_MFC_FLAG 1) 
Mientao answered 10/7, 2014 at 8:12 Comment(6)
@Royi for MSVC you should use the flags /MT /INCREMENTAL:NO /NODEFAULTLIB:MSVCRT. Xcode uses clang, thant the -static flag is all you needMientao
On Windows: SET(CMAKE_FIND_LIBRARY_SUFFIXES ".a;.dll.a")Rolypoly
target_link_libraries(your_target_name -static) this is awesome!Justin
A general CMake question here. CMake's design philosophy is that it is portable across GNU Make and MSVC. Why then would we need to use different CMake directives (and presumably platform detection predication in addition to that) in order for it to do its job?Pressing
@StevenLu because the compilers aren't standardized and every vendor makes its choicesMientao
instead of using target_compile_options(your_target_name [PUBLIC|PRIVATE] /MT), it is probably better to use the MSVC_RUNTIME_LIBRARY propertyAutocratic
G
4

Add these lines after add_executable(MyExec "main.c") (for example) :

target_link_libraries(MyExec PUBLIC "-static")

or before: link_libraries("-static")

Garrotte answered 29/3, 2017 at 13:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.