CMake Hello World

CMake Hello World


Compile a single source file

//main.c
#incldue<stdio.h>
int main()
{
    printf("Hello World!/n");
    return 0;
}

Then write a CMakeLists.txt main.c file in the same directory, as follows:

project(HELLO)
set(SRC_LIST main.c)
add_executable(hello ${SRC_LIST})

At the same time, create a build sub-folder in the same directory, used for an external compiler
into the build folder, call cmake:

$ cmake ..
$ make

After cmake will generate corresponding MakeFile, make CMakeLists.txt in accordance with certain rules are executable file hello

$ ./hello
$ Hello World!

The current directory structure:

+-- main.c
+-- CMakeLists.txt
+-- /build
    +--hello

The first line of the project is very important, in general, the statement need only appear once in the whole project, the statement CMakeLists.txt directory where all of its subdirectories will be CMakeLists.txt variable PROJECT_SOURCE_DIRvalues.

cmake will automatically define two variables:
PROJECT_BINARY_DIRrepresents the directory project generated binary file, usually a directory cmake command execution
PROJECT_SOURCE_DIRrepresents the directory where the project source files, understood as the directory where the project statement declares

By statement:
message("This is source dir: " ${PROJECT_SOURCE_DIR})
to display the default directory PROJECT_SOURCE_DIR.
set(SRC_LIST main.c)Set SRC_LISTvalue main.c
addexecutable(hello ${SRC_LIST})from SRC_LISTan executable file hello specified file

Second, multi-file compilation

The original split into three files main.c

//hello.h 头文件
void hello(const char * name);
//hello.c
#include<stdio.h>
#include"hello.h"

void hello(const char * name)
{   
    printf("Hello %s!\n",name);
}
//main.c
#include"hello.h"

int main()
{
    hello("World!");
    return 0;
}

CMakeLists.txt:

project(HELLO)
set(SRC_LIST main.c hello.c)
message("This is PROJECT_BINARY_DIR :"  ${PROJECT_BINARY_DIR})
message("This is PROJECT_SOURCE_DIR :"  ${PROJECT_SOURCE_DIR})
add_executable(hello ${SRC_LIST})

Third, generate a static library, the library link

By hello.c generate a static library libmyhello.a
modify the file as follows CMakeLists.txt

project(Hello)
set(LIB_SRC hello.c)
set(APP_SRC main.c)
add_library(myhello ${LIB_SRC})
add_executable(hello ${APP_SRC})
target_link_libraries(hello myhello)

One thing to note is that add_library(myhello ${LIB_SRC})the resulting static library archive file name will automatically add the prefix lib , which is obtained is called libmyhello.aa static library, and finally target_link_libraries(hello myhello)find a static library when looking for a named libmyhello.afile!

Fourth, the source files, libraries, header files in different folders

Now main.c hello.c hello.h under each project root directory create a folder to make it look more like a project.

At this folder are required to configure a CMakeLists.txt file for each file.

After each project directory as the source code to create folders as follows:

+-- CMakeLists.txt
+-- /src
    +-- main.c
    +-- CMakeLists.txt
+-- /lib
    +-- hello.c
    +-- hello.h
    +-- CMakeLists.txt
+-- /build

CMakeLists.txt file in the root directory of the project amended as follows:

project(Hello)
cmake_minimum_required(VERSION 3.5)

message("SOURCE_DIR: " ${PROJECT_SOURCE_DIR})
set(SRC_DIR ${PROJECT_SOURCE_DIR}/src)
set(LIB_DIR ${PROJECT_SOURCE_DIR}/lib)
set(BIN_DIR ${PROJECT_SOURCE_DIR}/bin)

add_subdirectory(${SRC_DIR} ${BIN_DIR})
add_subdirectory(${LIB_DIR} lib)

The aforementioned PROJECT_SOURCE_DIRvalue is the location where the project statement, so this value can be used as a global variable of the project directory.

add_subdirectory(${SRC_DIR} ${BIN_DIR})The first parameter represents the name of the subdirectory to be added, and the second parameter indicates generated after compiling the subdirectories and files intermediate results saved location .

So SRC_LISTthe result of the compilation will be stored in the secondary directory under the root directory of the project bin, the add_subdirectory(${LIB_DIR} lib)said LIB_DIRfiles compiled results will be saved in files under the lib directory folder execute cmake command, that is, three in the build directory lib secondary lib directory rather than the root directory of the project under

When not using the second parameter, intermediate results and files will be saved in the src and lib directory build directory.

src 中的 CMakeLists.txt

include_directories(${PROJECT_SOURCE_DIR}/lib)
set(APP_SRC main.c)
add_executable(hello ${APP_SRC})
target_link_libraries(hello myhello)

Because the src folder will be add to the project root directory, it ${PROJECT_SOURCE_DIR}can be used as a global variable. It represents the header file directory for the lib file in the project root folder

lib in CMakeLists.txt

set(LIB_SRC hello.c)
add_library(myhello ${LIB_SRC})

Specify the location of the target file and library files separately

Documents/
├── bin
│   ├── ...
│   ├── hello
│   └── Makefile
├── build
│   ├── ...
│   ├── lib
│   │   ├── CMakeFiles
│   │   │   ├── ...
│   │   ├── libmyhello.a
│   │   └── Makefile
│   └── Makefile
├── CMakeLists.txt
├── lib
│   ├── CMakeLists.txt
│   ├── hello.c
│   ├── hello.h
└── src
    ├── CMakeLists.txt
    └── main.c

According to previous compilation rules, we finally get the tree above. Documents are the root of our project, the target executable file hello saved in two directories bin, static library archive files saved in three libmyhello.a lib directory under the build in.

In order to achieve separation of the resulting compiled "cream" and the various intermediate file CMake can further specify the "essence file" save location.

lib/CMakeLists.txt

set(LIB_SRC hello.c)
add_library(myhello ${LIB_SRC})
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/build_res/lib)

src/CMakeLists.txt:

include_directories(${PROJECT_SOURCE_DIR}/lib)
set(APP_SRC main.c)
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/build_res/bin)
add_executable(hello ${APP_SRC})
target_link_libraries(hello myhello)

By specify LIBRARY_OUTPUT_PATHand EXECUTABLE_OUTPUT_PATH, compile the make and libmyhello.a hello obtained with CMake intermediate file may be separated, are stored in the project root build_res under / bin and build_res / lib of. The CMake and intermediate files will be saved with the Makefile in the build directory.

Fifth, the use of dynamic libraries

install instructions

CMAKE_INSTALL_PREFIXCommon variables used as follows:
cmake -DCMAKE_INSTALL_PREFIX=/usr .

INSTALL(TARGETS targets... [[ARCHIVE|LIBRARY|RUNTIME] 
                            [DESTINATION <dir>]
                            [PERMISSIONS permissions...]
                            [CONFIGURATIONS[Debug|Release|...]]
                            [COMPONENT <component>]
                            [OPTIONAL]] 
                            [...])

targetsParameter is passed add_executableand the add_librarytarget file name is set, the target file three types, ARCHIVE, LIBRARY, RUNTIMErespectively static library, dynamic library object files and executables. DESTINATIONThe default path specified relative CMAKE_INSTALL_PREFIXrelative path.

install(TARGETS myrun mylib mystaticlib
    RUNTIME DESTINATION bin
    LIBRARY DESTINATION lib
    ARCHIVE DESTINATION libstatic
    )

The above command, the target executable file myrun installed ${CMAKE_INSTALL_PREFIX}/binunder the shared library mylib installed ${CMAKE_INSTALL_PREFIX}/lib, install the static library mystaticlib to ${CMAKE_INSTALL_PREFIX}/libstaticthe next. If the DESTINATINOspecified path is absolute, it is CMAKE_INSTALL_PREFIXinvalid.

Such as the file is organized as follows:

t3/
├── build
├── CMakeLists.txt
├── lib
│   ├── CMakeLists.txt
│   ├── hello.c
│   └── hello.h
└── main.c

CMakeLists.txt top reads as follows:

project(HELLO)
cmake_minimum_required(VERSION 3.5)

set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/res_lib)
set(PROJ_SRC main.c)

add_subdirectory(lib)

add_executable(mainhello ${PROJ_SRC})
target_link_libraries(mainhello hello)
install(TARGETS mainhello 
        RUNTIME DESTINATION install_bin)

lib folder CMakeLists.txt

set(LIBHELLO_SRC hello.c)

add_library(hello SHARED ${LIBHELLO_SRC})
add_library(hello_static STATIC ${LIBHELLO_SRC})
set_target_properties(hello_static PROPERTIES OUTPUT_NAME "hello")

set_target_properties(hello PROPERTIES VERSION 1.2 SOVERSION 1)
install(TARGETS hello hello_static 
        LIBRARY DESTINATION install_lib 
        ARCHIVE DESTINATION install_static)

In the build in execution

cmake -DCMAKE_INSTALL_PREFIX=../ ..
make 
sudo make install

-DCMAKE_INSTALL_PREFIXThe default address for the /usr/local
install instructions can be used for files, directories, scripts and so on target.

Use external shared library and header files

Previously used include_directoriescommands

include_directories([AFTER|BEFORE] [SYSTEM] dir1 dir2 ...)

set(CMAKE_INCLUDE_DIRECTORIES_BEFORE ON)Variable CMAKE_INCLUDE_DIRECTORIES_BEFOREis set to ON, the include path manually added before existing priority path. There after the corresponding

link_directoriesSettings need to link the path to the library
target_link_libraries(target library1 <debug | optimized> library2 ...)to add a link libraries need to target.

find_path(myHeader NAMES hello.h PATHS /usr/inlcude /usr/include/hello)
findpath instructions for the specified folder to find the specified file and the folder where the file assigned to the corresponding variable
find_library find_path and acts like, but will find_library file path assigned to the variable, rather than the folder in the file path.

The default search path environment variable CMAKE_INCLUDE_PATHand CMAKE_LIBRARY_PATHspecified. Both environment variables represent only cmake command in find_path and find_library default search path, it does not mean that cmake will automatically search for header files and libraries from the path. In other words, if you do not use find_ instruction, then the two environment variables is invalid.

Prior assumptions hello.h header files are installed to the folder /usr/local/include, obtained after compiling shared libraries libhello.so libhello.so.1 libhello.so.1.2 be installed to a file folder/usr/local/install_lib

Now in order to use the shared library before compiling get, we write main.c use the library. main.c saved in the root directory of the project src t3 in

#include <hello.h>

int main.c
{
    HelloFunc();
    return 0;
}

t3 in CMakeLists.txt:

project(HELLOLIB)
cmake_minimum_required(VERSION 3.5)

find_path(myheader hello.h)
if(myheader)
message("myheader: " ${myheader})
# myheader 保存的是hello.h所在文件夹的路径
include_directories(${myheader})
endif(myheader)

find_library(mylibrary hello)
if(mylibrary)
# mylibrary 保存的是 hello 库文件本身的路径
# 所以不需要 link_directories
message("mylibrary: " ${mylibrary})
endif(mylibrary)

add_subdirectory(src)

src中的CMakeLists.txr

set(SRC_LIST main.c)
add_executable(mainhello ${SRC_LIST})
# mylibrary 继承自 parent CMakeLists.txt 生成的对象
target_link_libraries(mainhello ${mylibrary})
install(TARGETS mainhello RUNTIME DESTINATION install_bin)

The whole project folder structure as follows:

t3/
├── build
├── CMakeLists.txt
└── src
    ├── CMakeLists.txt
    └── main.c

Enter the build directory, set environment variables, start the compilation process

# find_path 的默认路径
export CMAKE_INCLUDE_PATH=/usr/local/include
# find_lirary 的默认路径
export CMAKE_LIBRARY_PATH=/usr/local/install_lib
cmake -DCMAKE_INSTALL_PREFIX=../ ..

-- The C compiler identification is GNU 5.4.0
-- The CXX compiler identification is GNU 5.4.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
myheader: /usr/local/include
mylibrary: /usr/local/lib/libhello.so
-- Configuring done
-- Generating done
-- Build files have been written to: /home/hzq0/Documents/t3/build

Can be seen that myheaderthe value / usr / local / include, but mylibrarythe value of/usr/local/lib/libhello.so

cmake VERBOSE=1
/usr/bin/cmake -H/home/hzq0/Documents/t3 -B/home/hzq0/Documents/t3/build --check-build-system CMakeFiles/Makefile.cmake 0
/usr/bin/cmake -E cmake_progress_start /home/hzq0/Documents/t3/build/CMakeFiles /home/hzq0/Documents/t3/build/CMakeFiles/progress.marks
make -f CMakeFiles/Makefile2 all
make[1]: Entering directory '/home/hzq0/Documents/t3/build'
make -f src/CMakeFiles/mainhello.dir/build.make src/CMakeFiles/mainhello.dir/depend
make[2]: Entering directory '/home/hzq0/Documents/t3/build'
cd /home/hzq0/Documents/t3/build && /usr/bin/cmake -E cmake_depends "Unix Makefiles" /home/hzq0/Documents/t3 /home/hzq0/Documents/t3/src /home/hzq0/Documents/t3/build /home/hzq0/Documents/t3/build/src /home/hzq0/Documents/t3/build/src/CMakeFiles/mainhello.dir/DependInfo.cmake --color=
Dependee "/home/hzq0/Documents/t3/build/src/CMakeFiles/mainhello.dir/DependInfo.cmake" is newer than depender "/home/hzq0/Documents/t3/build/src/CMakeFiles/mainhello.dir/depend.internal".
Dependee "/home/hzq0/Documents/t3/build/src/CMakeFiles/CMakeDirectoryInformation.cmake" is newer than depender "/home/hzq0/Documents/t3/build/src/CMakeFiles/mainhello.dir/depend.internal".
Scanning dependencies of target mainhello
make[2]: Leaving directory '/home/hzq0/Documents/t3/build'
make -f src/CMakeFiles/mainhello.dir/build.make src/CMakeFiles/mainhello.dir/build
make[2]: Entering directory '/home/hzq0/Documents/t3/build'
[ 50%] Building C object src/CMakeFiles/mainhello.dir/main.c.o
cd /home/hzq0/Documents/t3/build/src && /usr/bin/cc   -I/usr/local/include   -o CMakeFiles/mainhello.dir/main.c.o   -c /home/hzq0/Documents/t3/src/main.c
[100%] Linking C executable mainhello
cd /home/hzq0/Documents/t3/build/src && /usr/bin/cmake -E cmake_link_script CMakeFiles/mainhello.dir/link.txt --verbose=1
/usr/bin/cc     CMakeFiles/mainhello.dir/main.c.o  -o mainhello /usr/local/install_lib/libhello.so -Wl,-rpath,/usr/local/install_lib: 
make[2]: Leaving directory '/home/hzq0/Documents/t3/build'
[100%] Built target mainhello
make[1]: Leaving directory '/home/hzq0/Documents/t3/build'
/usr/bin/cmake -E cmake_progress_start /home/hzq0/Documents/t3/build/CMakeFiles 0

make install 

[100%] Built target mainhello
Install the project...
-- Install configuration: ""
-- Installing: /home/hzq0/Documents/t3/install_bin/mainhello
-- Set runtime path of "/home/hzq0/Documents/t3/install_bin/mainhello" to ""

note

hzq0@ceph0:~/Documents/t3/build/src$ ldd mainhello 
    linux-vdso.so.1 =>  (0x00007fffe7be6000)
    libhello.so.1 => /usr/local/install_lib/libhello.so.1 (0x00007f5289427000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f528905d000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f5289629000)
hzq0@ceph0:~/Documents/t3/build/src$ cd ../../install_bin/
hzq0@ceph0:~/Documents/t3/install_bin$ ldd mainhello 
    linux-vdso.so.1 =>  (0x00007ffe56dfa000)
    libhello.so.1 => not found
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f9f91c61000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f9f9202b000)

Different relocation table portion of the executable file executable object file obtained and make make install obtained. The machine needs to link the former path of the shared library is written executable file, and the latter does not . When the loader loads the latter from the system default, or the environment variable LD_LIBRARY_PATHadditional address to find dynamic link library, installed in front of the shared library that we do not install it in the default path, so that the latter can not locate the shared library at run time .

Guess you like

Origin www.cnblogs.com/hezhiqiangTS/p/11931172.html