Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert Makefile into CMakeLists, where to start

Tags:

makefile

cmake

I searched on the inet but I did not find any clear answer. Could you point me in the right direction on how to convert a Makefile into a CMakeLists?

I want to do that because I am new both to makefile and to cmake. In my job CMake is more used and since I need to start using one of them I prefer having everything in CMake. I know CMake is generating a Makefile but for me CMake is way easier to read than a Makefile.

I have the following Makefile:

PREFIX ?= /usr/local

CC = gcc
AR = ar

CFLAGS = -std=gnu99 -fPIC -Wall -Wno-unused-parameter -Wno-unused-function -I. -O4

APRILTAG_SRCS := $(shell ls *.c common/*.c)
APRILTAG_HEADERS := $(shell ls *.h common/*.h)
APRILTAG_OBJS := $(APRILTAG_SRCS:%.c=%.o)
TARGETS := libapriltag.a libapriltag.so 
# LIBS := -Lusr/include/flycapture

.PHONY: all
all: $(TARGETS)
    @$(MAKE) -C example all

.PHONY: install
install: libapriltag.so
    @chmod +x install.sh
    @./install.sh $(PREFIX)/lib libapriltag.so #this should be the line that install the library
    @./install.sh $(PREFIX)/include/apriltag $(APRILTAG_HEADERS)
    @sed 's:^prefix=$$:prefix=$(PREFIX):' < apriltag.pc.in > apriltag.pc
    @./install.sh $(PREFIX)/lib/pkgconfig apriltag.pc
    @rm apriltag.pc
    @ldconfig

libapriltag.a: $(APRILTAG_OBJS)
    @echo "   [$@]"
    @$(AR) -cq $@ $(APRILTAG_OBJS)

libapriltag.so: $(APRILTAG_OBJS)
    @echo "   [$@]"
    @$(CC) -fPIC -shared -o $@ $^

%.o: %.c
    @echo "   $@"
    @$(CC) -o $@ -c $< $(CFLAGS)

.PHONY: clean
clean:
    @rm -rf *.o common/*.o $(TARGETS)
    @$(MAKE) -C example clean

I am not asking you to do my job but I would like to have some kind of guide or a good link where to look.

The project contains both C and C++ programming languages.

I started creating a new CMakeLists.txt file, but it is still not working. It gives me the following errors: You have called ADD_LIBRARY for library librapriltag.a without any source files. This typically indicates a problem with your CMakeLists.txt file

-- Configuring done
CMake Error: Cannot determine link language for target "librapriltag.a".
CMake Error: CMake can not determine linker language for target: librapriltag.a
-- Generating done
-- Build files have been written to: .....

The CMakeLists.txt I started creating is the following:

project( apriltag2 C CXX)

cmake_minimum_required(VERSION 2.8)

set(CMAKE_C_FLAGS "-std=gnu99 -fPIC -Wall -Wno-unused-parameter -Wno-unused-function -I. -O4")

include_directories("/home/fschiano/Repositories/apriltag2")
include_directories("/home/fschiano/Repositories/apriltag2/common")

add_library( librapriltag.a )

The CMakeLists.txt which works is the following:

project( apriltag2 )

cmake_minimum_required(VERSION 2.8)

set(CMAKE_C_FLAGS "-std=gnu99 -fPIC -Wall -Wno-unused-parameter -Wno-unused-function -I. -O4")

message("CMAKE_SOURCE_DIR=${CMAKE_SOURCE_DIR}")

file(GLOB apriltag_SRC "*.c")
file(GLOB apriltag_HEADERS "*.h")

set(APRILTAG_SRCS ${apriltag_SRC})
set(APRILTAG_HEADERS ${apriltag_HEADERS})

message(STATUS "CMAKE_CURRENT_LIST_DIR=${CMAKE_CURRENT_LIST_DIR}")

add_library(apriltag STATIC ${APRILTAG_SRCS})

target_include_directories(apriltag PUBLIC ${CMAKE_SOURCE_DIR})
target_compile_options(apriltag PUBLIC -fPIC -Wall -Wno-unused-parameter -Wno-unused-function -O4)

install(TARGETS apriltag
        ARCHIVE DESTINATION lib
        RUNTIME DESTINATION bin
        LIBRARY DESTINATION lib)
install(DIRECTORY CMAKE_CURRENT_LIST_DIR/include/
        DESTINATION CMAKE_CURRENT_LIST_DIR/include/
        FILES_MATCHING PATTERN *.h)

EDIT:

Something is still not right. If I want to change something in my library, like something which is in /home/fschiano/Repositories/apriltag2/common If I use the Makefile which I had before doing all these modifications and I do:

  1. make

  2. do some modifications in the files I wanted to modify

  3. sudo make install, which would give me the following output:

    /usr/local/lib/libapriltag.so
    /usr/local/include/apriltag/apriltag.h
    /usr/local/include/apriltag/common/g2d.h
    /usr/local/include/apriltag/common/getopt.h
    /usr/local/include/apriltag/common/homography.h
    /usr/local/include/apriltag/common/image_f32.h
    /usr/local/include/apriltag/common/image_u8.h
    /usr/local/include/apriltag/common/image_u8x3.h
    /usr/local/include/apriltag/common/matd.h
    /usr/local/include/apriltag/common/math_util.h
    /usr/local/include/apriltag/common/pnm.h
    /usr/local/include/apriltag/common/postscript_utils.h
    /usr/local/include/apriltag/common/string_util.h
    /usr/local/include/apriltag/common/svd22.h
    /usr/local/include/apriltag/common/thash_impl.h
    /usr/local/include/apriltag/common/timeprofile.h
    /usr/local/include/apriltag/common/time_util.h
    /usr/local/include/apriltag/common/unionfind.h
    /usr/local/include/apriltag/common/workerpool.h
    /usr/local/include/apriltag/common/zarray.h
    /usr/local/include/apriltag/common/zhash.h
    /usr/local/include/apriltag/common/zmaxheap.h
    /usr/local/include/apriltag/tag16h5.h
    /usr/local/include/apriltag/tag25h7.h
    /usr/local/include/apriltag/tag25h9.h
    /usr/local/include/apriltag/tag36artoolkit.h
    /usr/local/include/apriltag/tag36h10.h
    /usr/local/include/apriltag/tag36h11.h
    /usr/local/lib/pkgconfig/apriltag.pc
    /sbin/ldconfig.real: /usr/lib/libstdc++.so.5 is not a symbolic link
    
    

and the modifications would take effect.

Now, if I remove the Makefile and I do:

  1. cmake .

  2. make

  3. do some modifications in the files I wanted to modify

  4. sudo make install, it gives me the following output:

    Install the project... -- Install configuration: "" -- Up-to-date: /usr/local/lib/libapriltag.a

So it seems that the install part of the CMakeLists.txt is not right!

The file install.sh is the following.

#!/bin/sh -e
# Usage: install.sh TARGET [RELATIVE PATHS ...]
#
# e.g. ./install.sh /usr/local foo/file1 foo/file2 ...
# This creates the files /usr/local/foo/file1 and /usr/local/foo/file2

TARGETDIR=$1
shift

for src in "$@"; do
    dest=$TARGETDIR/$src
    mkdir -p $(dirname $dest)
    cp $src $dest
    echo $dest
done

Could you try to help me? Thanks

like image 564
desmond13 Avatar asked Nov 29 '16 08:11

desmond13


People also ask

How do I convert a file to CMake?

In converting an autoconf based project to CMake, start with the configure.in and Makefile.in files. The Makefile.in file can be converted to CMake syntax as explained in the preceding section on converting UNIX Makefiles. Once this has been done, convert the configure.in file into CMake syntax.

Where should CMakeLists TXT be?

CMakeLists. txt file contains a set of directives and instructions describing the project's source files and targets (executable, library, or both). When you create a new project, CLion generates CMakeLists. txt file automatically and places it in the project root directory.

Is CMakeLists TXT a Makefile?

CMake is a generator of build systems that can produce Makefiles for Unix like systems, Visual Studio Solutions for Windows and XCode projects for Mac OS. All these from the same base – a single CMakeLists. txt file.


2 Answers

Let's go through that step-by-step:

PREFIX ?= /usr/local

We ignore that, as it's the default. Can be overwritten by CMAKE_INSTALL_PREFIX.

CC = gcc
AR = ar

Ignore these as well. Use CMAKE_C_COMPILER and CMAKE_CXX_COMPILER to forcibly switch the compiler.

CFLAGS = -std=gnu99 -fPIC -Wall -Wno-unused-parameter -Wno-unused-function -I. -O4

They are pretty special for gcc-like compilers. Set them conditionally for CMAKE_C_COMPILER_ID MATCHES GNU further down after defining the target. The standard is set by set(C_STANDARD 98) and set(CXX_STANDARD 98).

APRILTAG_SRCS := $(shell ls *.c common/*.c)

Define a variable listing all the source files individually: set(APRILTAG_SRCS ...)

APRILTAG_HEADERS := $(shell ls *.h common/*.h)

Define a variable listing all the header file individually: set(APRILTAG_HEADERS ...). However, you don't really need them anywhere (unless you want Visual Studio to list them).

APRILTAG_OBJS := $(APRILTAG_SRCS:%.c=%.o)

In most cases, you don't need that. For those rare cases there are Object Libraries.

TARGETS := libapriltag.a libapriltag.so 
# LIBS := -Lusr/include/flycapture

We define our libraries here with add_library:

add_library(apriltag ${APRILTAG_SRCS})
target_include_directories(apriltag PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include/apriltag)
target_compile_options(apriltag PUBLIC -fPIC -Wall -Wno-unused-parameter -Wno-unused-function -O4)

The switch between static and shared is done via BUILD_SHARED_LIBS on invocation of CMake.

.PHONY: all
all: $(TARGETS)
    @$(MAKE) -C example all

Nothing to do here. CMake will automatically create that.

.PHONY: install
install: libapriltag.so
    @chmod +x install.sh
    @./install.sh $(PREFIX)/lib libapriltag.so #this should be the line that install the library
    @./install.sh $(PREFIX)/include/apriltag $(APRILTAG_HEADERS)
    @sed 's:^prefix=$$:prefix=$(PREFIX):' < apriltag.pc.in > apriltag.pc
    @./install.sh $(PREFIX)/lib/pkgconfig apriltag.pc
    @rm apriltag.pc
    @ldconfig

CMake will ease this up by a magnitude:

install(TARGETS apriltag
        ARCHIVE DESTINATION lib
        RUNTIME DESTINATION bin
        LIBRARY DESTINATION lib)
install(DIRECTORY include/
        DESTINATION include/
        FILES_MATCHING PATTERN *.h)

That will install the library static and shared library (whatever exists) and the header files.

libapriltag.a: $(APRILTAG_OBJS)
    @echo "   [$@]"
    @$(AR) -cq $@ $(APRILTAG_OBJS)

libapriltag.so: $(APRILTAG_OBJS)
    @echo "   [$@]"
    @$(CC) -fPIC -shared -o $@ $^

%.o: %.c
    @echo "   $@"
    @$(CC) -o $@ -c $< $(CFLAGS)

All this is not needed.

.PHONY: clean
clean:
    @rm -rf *.o common/*.o $(TARGETS)
    @$(MAKE) -C example clean

You don't need that. CMake will generate a clean target automatically.

like image 97
Torbjörn Avatar answered Oct 23 '22 13:10

Torbjörn


Judging from TARGETS := libapriltag.a libapriltag.so, you'll defintely need add_library command to create targets.

Instead of gathering souces to be compiled using wildcards like APRILTAG_SRCS := $(shell ls *.c common/*.c) it is recommended to list them explicitly in add_library call. But if you really want to list them automatically, see file(GLOB ...) command. (There are some important things to be aware of, though, see Specify source files globally with GLOB?).

The clean target would be generated automatically by CMake.

Finally, see the documentation for install() command to create install rules.

Compiler flags are set using set(CMAKE_C_FLAGS "blabla"), or appended using set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} blabla").

like image 40
arrowd Avatar answered Oct 23 '22 12:10

arrowd