Ответ 1
Следующий файл Makefile создает исполняемый файл с именем prog
из источников
prog1.c, prog2.c, prog3.c and main.c
. prog
связан с libmystatlib.a
и libmydynlib.so
, которые также построены из источника. Кроме того, prog
использует
библиотека libstuff.a
в stuff/lib
и ее заголовок в stuff/include
.
Makefile по умолчанию создает цель релиза, но также предлагает цель отладки:
#Makefile
CC = gcc
CPP = g++
RANLIB = ar rcs
RELEASE = -c -O3
DEBUG = -c -g -D_DEBUG
INCDIR = -I./stuff/include
LIBDIR = -L./stuff/lib -L.
LIBS = -lstuff -lmystatlib -lmydynlib
CFLAGS = $(RELEASE)
PROGOBJS = prog1.o prog2.o prog3.o
prog: main.o $(PROGOBJS) mystatlib mydynlib
$(CC) main.o $(PROGOBJS) $(LIBDIR) $(LIBS) -o prog
debug: CFLAGS=$(DEBUG)
debug: prog
mystatlib: mystatlib.o
$(RANLIB) libmystatlib.a mystatlib.o
mydynlib: mydynlib.o
$(CPP) -shared mydynlib.o -o libmydynlib.so
%.o: %.c
$(CC) $(CFLAGS) $(INCDIR) $< -o [email protected]
%.o: %.cpp
$(CPP) $(CFLAGS) $(INCDIR) -fPIC $< -o [email protected]
Вот CMakeLists.txt
, который делает (почти) то же самое, с некоторыми комментариями, чтобы подчеркнуть
сходство с Makefile:
#CMakeLists.txt
cmake_minimum_required(VERSION 2.8) # stuff not directly
project(example) # related to building
include_directories(${CMAKE_SOURCE_DIR}/stuff/include) # -I flags for compiler
link_directories(${CMAKE_SOURCE_DIR}/stuff/lib) # -L flags for linker
set(PROGSRC prog1.c prog2.c prog3.c) # define variable
add_executable(prog main.c ${PROGSRC}) # define executable target prog, specify sources
target_link_libraries(prog mystatlib mydynlib stuff) # -l flags for linking prog target
add_library(mystatlib STATIC mystatlib.c) # define static library target mystatlib, specify sources
add_library(mydynlib SHARED mydynlib.cpp) # define shared library target mydynlib, specify sources
#extra flags for linking mydynlib
set_target_properties(mydynlib PROPERTIES POSITION_INDEPENDENT_CODE TRUE)
#alternatively:
#set_target_properties(mydynlib PROPERTIES COMPILE_FLAGS "-fPIC")
В этом простом примере наиболее важными отличиями являются:
-
CMake распознает, какие компиляторы использовать для какого типа источника. Кроме того, это вызывает правильную последовательность команд для каждого типа цели. Поэтому там не имеет явной спецификации команд, таких как $(CC)..., $(RANLIB)... и т.д.
-
Все обычные флаги компилятора/компоновщика, касающиеся включения файлов заголовков, библиотек и т.д. заменяются независимыми/независимыми от платформы независимыми командами.
-
Флаги отладки включаются путем установки переменной CMAKE_BUILD_TYPE в "Debug", или передав его в CMake при вызове программы:
cmake -DCMAKE_BUILD_TYPE:STRING=Debug
. -
CMake предлагает также независимое от платформы включение флага -fPIC (через свойство POSITION_INDEPENDENT_CODE) и многие другие. Тем не менее, более неясные настройки могут быть реализованы вручную в CMake так же, как и в Makefile (с помощью
COMPILE_FLAGS
и аналогичные свойства). Конечно, CMake действительно начинает сиять, когда третья сторона библиотеки (например, OpenGL) включены в переносимую манеру. -
Процесс сборки имеет один шаг, если вы используете Makefile, а именно: введите
make
в командной строке. Для CMake есть два шага: во-первых, вам нужно настроить среду сборки (либо набравcmake <source_dir>
в каталоге сборки, либо запустив некоторый клиент GUI). Это создает Makefile или что-то эквивалентное, в зависимости от выбранной вами системы сборки (например, make в Unixes или VС++ или MinGW + Msys в Windows). Система сборки может быть передана CMake в качестве параметра; однако CMake делает разумные варианты по умолчанию в зависимости от конфигурации вашей системы. Во-вторых, вы выполняете фактическую сборку в выбранной системе сборки.
Источники и инструкции по созданию доступны в https://github.com/rhoelzel/make_cmake.