Soheilmn
Soheilmn

Reputation: 29

How to create a CMake file from an existing Makefile?

I am trying to migrate my C++ code to CLion on Mac OSX, but I am new to CMake. I have a C++ code, which has been tested in Eclipse and works successfully. In particular, I have created the Eclipse project by setting the project properties according to the following Makefile.

SYSTEM     = x86-64_osx
LIBFORMAT  = static_pic

CPLEXDIR = /Users/soheilmn/Applications/IBM/ILOG/CPLEX_Studio1271
CONCERTDIR = /Users/soheilmn/Applications/IBM/ILOG/CPLEX_Studio1271/concert

# ---------------------------------------------------------------------
# Compiler selection 
# ---------------------------------------------------------------------
CCC = clang++ -O0


# ---------------------------------------------------------------------
# Compiler options 
# ---------------------------------------------------------------------
CCOPT = -m64 -O -fPIC -fexceptions -DNDEBUG -DIL_STD -stdlib=libc++

# ---------------------------------------------------------------------
# Link options and libraries
# ---------------------------------------------------------------------

CPLEXBINDIR   = $(CPLEXDIR)/bin/$(BINDIST)
CPLEXLIBDIR   = $(CPLEXDIR)/lib/$(SYSTEM)/$(LIBFORMAT)
CONCERTLIBDIR = $(CONCERTDIR)/lib/$(SYSTEM)/$(LIBFORMAT)

CCLNDIRS  = -L$(CPLEXLIBDIR) -L$(CONCERTLIBDIR)
CCLNFLAGS = -lconcert -lilocplex -lcplex -m64 -lm -lpthread -framework CoreFoundation -framework IOKit -stdlib=libc++

all:
    make all_cpp
execute: all
    make execute_cpp

CONCERTINCDIR = $(CONCERTDIR)/include
CPLEXINCDIR   = $(CPLEXDIR)/include

CCFLAGS = $(CCOPT) -I$(CPLEXINCDIR) -I$(CONCERTINCDIR) 

Here is what I have created so far for the CMakeLists.txt file.

cmake_minimum_required(VERSION 3.9)
project(SFCNF CXX)
set(CMAKE_CXX_STANDARD 11)

include_directories(/Users/soheilmn/Applications/IBM/ILOG/CPLEX_Studio1271/cplex/include)
include_directories(/Users/soheilmn/Applications/IBM/ILOG/CPLEX_Studio1271/concert/include)

set(CMAKE_CXX_FLAGS "-O0 -c -m64 -fPIC  -DNDEBUG -DIL_STD -stdlib=libc++")

link_directories("/Users/soheilmn/Applications/IBM/ILOG/CPLEX_Studio1271/concert/lib/x86-64_osx/static_pic")
link_directories("/Users/soheilmn/Applications/IBM/ILOG/CPLEX_Studio1271/cplex/lib/x86-64_osx/static_pic")

add_executable(SFCNF "/Users/soheilmn/CLionProjects/SFCNF/main.cpp")

target_Link_Libraries(SFCNF "-lconcert -lilocplex -lcplex -m64 -lm -lpthread -framework CoreFoundation -framework IOKit -stdlib=libc++")

In CLion, when I click on the "Build" button, I see "Built target SFCNF" message (with a number of warnings). But, when I run the program, I see the following message:

"File not found: /Users/soheilmn/CLionProjects/SFCNF/cmake-build-debug/SFCNF"

Can anyone please tell me what I am missing here? Thanks!

Update: I edited my CMake file as follows.

cmake_minimum_required(VERSION 3.9)
project(SFCNF CXX)
set(CMAKE_CXX_STANDARD 11)
add_executable(SFCNF main.cpp)

With a simple Hello World program, my C++ code now works in CLion. However, when I set the compiler options like below

cmake_minimum_required(VERSION 3.9)
project(SFCNF CXX)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS "-O0 -c -m64 -fPIC  -DNDEBUG -DIL_STD -stdlib=libc++")
add_executable(SFCNF main.cpp)

CLion produces a number of warnings as follows.

/Applications/CLion.app/Contents/bin/cmake/bin/cmake --build /Users/soheilmn/CLionProjects/SFCNF/cmake-build-debug --target SFCNF -- -j 2

[ 50%] Linking CXX executable SFCNF
clang: warning: -Wl,-search_paths_first: 'linker' input unused [-Wunused-command-line-argument]
clang: warning: -Wl,-headerpad_max_install_names: 'linker' input unused [-Wunused-command-line-argument]
clang: warning: CMakeFiles/SFCNF.dir/main.cpp.o: 'linker' input unused [-Wunused-command-line-argument]
clang: warning: argument unused during compilation: '-O0' [-Wunused-command-line-argument]
clang: warning: argument unused during compilation: '-fPIC' [-Wunused-command-line-argument]
clang: warning: argument unused during compilation: '-D NDEBUG' [-Wunused-command-line-argument]
clang: warning: argument unused during compilation: '-D IL_STD' [-Wunused-command-line-argument]
clang: warning: argument unused during compilation: '-stdlib=libc++' [-Wunused-command-line-argument]
clang: warning: argument unused during compilation: '-g' [-Wunused-command-line-argument]
[100%] Built target SFCNF

Moreover, now if I modify my program to print another message, CLion keeps running the previous Hello World program as if I have not modified anything in the main.cpp file.

Upvotes: 1

Views: 3728

Answers (1)

ComicSansMS
ComicSansMS

Reputation: 54737

Do not manually set compile flags in CMake like that.

Instead, use the respective CMake features to achieve what those flags where supposed to do:

  • -O0 the level of optimization is typically determined by the CMAKE_BUILD_TYPE. Note that this is a variable that will be set by the user when invoking CMake, so you should only ever read from that variable in the CMakeLists.txt.
  • -c CMake properly separates compile and link steps, just never pass this option.
  • -m64 The machine type is determined by the compiler being used (for Makefiles) or the generator (on Visual Studio). If you need to manually choose a different machine type, you will need a toolchain file. Unless you are cross-compiling, you almost certainly just want to skip this option.
  • -fPIC This is done by setting the POSITION_INDEPENDENT_CODE target property. You can also set this globally for all targets by setting the CMAKE_POSITION_INDEPENDENT_CODE variable.
  • -DNDEBUG This is again set automatically based on the CMAKE_BUILD_TYPE.
  • -DIL_STD Use target_compile_definitions to set preprocessor defines.
  • -stdlib=libc++" First be sure that you actually need this. This is again a toolchain dependent option, and one that highly depends on the build environment. So you will want to at least escape it behind a generator expression to make sure it is only invoked for the toolchains where it applies. You might even consider moving it to a toolchain file as well.

All of that being said: There is no easy 1:1 conversion from Makefiles to CMake.

Both systems have vastly different scopes and use completely different idioms. In particular, CMake needs to be portable to a lot of underlying build systems, so a lot of the shortcuts that make can use are not supported by CMake. For instance, the link_directories approach that you used is usually a really bad idea in CMake. Be sure you first get familiar with how CMake does these things before proceeding.

Upvotes: 2

Related Questions