I converted an old style makefile to a CMake CMakeLists.txt file so that I can load a project into JetBrain's new CLion IDE.
I thought it would be easy, but I'm stuck at the point of CMake appending some custom compiler flags to the compilation command which cause a compilation error. I don't have enough knowledge of CMake to solve this issue.
Here is the original makefile.
# makefile
# Main Filename to be compiled
MAINFILE = TestProgram
# Paths
DRIVE := C:
COMPILERROOT := $(DRIVE)/GNUHC11
COMPILERPATH := $(COMPILERROOT)/bin
GELROOT := $(DRIVE)/library/gel-hc1x-1.6.1
GELINCLUDESDIR := $(GELROOT)/include
# Compiler, Linker, Object Copy, and Object Dump path
CC := $(COMPILERPATH)/m6811-elf-gcc # compiler
OC := $(COMPILERPATH)/m6811-elf-objcopy # object copy
OD := $(COMPILERPATH)/m6811-elf-objdump # object dump
# Includes
GELINCLUDES += -I$(GELINCLUDESDIR) -I$(GELINCLUDESDIR)/asm-m68hc11/arch-32k
# Compiler Flags
CFLAGS += -Os # turn on optimizer
CFLAGS += -mshort # consider type int to be 16 bits
CFLAGS += -Wl,-m,m68hc11elfb # build for elf file and use memory.x for memory map
CFLAGS += -I. $(GELINCLUDES) # Add current dir and gel library for includes
CFLAGS += -Dmc6811 # Add define to define the processor architecture for gel includes
# C Source codes to be compiled
SRC1 = $(MAINFILE).c
SRC2 = Interrupts.c
SRC3 = Utilities.c
# C Header files dependencies
HDR1 = $(MAINFILE).h
HDR2 = Interrupts.h
HDR3 = Utilities.h
SRCS = $(SRC1) $(SRC2) $(SRC3)
HDRS = $(HDR1) $(HDR2) $(HDR3)
# Elf file to be generated
ELF1 = $(SRC1:.c=.elf)
# Generate Bin file for programming & Assembly dump
$(MAINFILE).bin : $(ELF1)
$(OC) -O binary $(ELF1) $(MAINFILE).bin
$(OD) -xDC --section=.text --section=.vectors $(ELF1) >$(MAINFILE).dump
# Full compile and link
$(ELF1) : $(SRCS) $(HDRS)
$(CC) $(CFLAGS) -o $(ELF1) $(SRCS)
clean ::
del *.dump
del *.elf
del *.bin
And here is my attempt at the CMakeLists.txt file.
cmake_minimum_required(VERSION 2.8.4)
# program names
set(HC11C m6811-elf-gcc.exe)
set(OBJCOPY m6811-elf-objcopy.exe)
set(OBJDUMP m6811-elf-objdump.exe)
# Important project paths
set(LIB_INC_PATH "C:/library/gel-hc1x-1.6.1/include"
"C:/library/gel-hc1x-1.6.1/include/asm-m68hc11/arch-32k")
set(HC11C_PATH "C:/GNUHC11/bin")
# Sets the compiler
# Needs to come before the project function
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_C_COMPILER "${HC11C_PATH}/${HC11C}")
set(MAIN_FILE "TestProgram")
project(${MAIN_FILE})
# Files to be compiled
set(BASE_PATH "${${PROJECT_NAME}_SOURCE_DIR}")
set(INC_PATH "${BASE_PATH}")
set(SRC_PATH "${BASE_PATH}")
set(SRC_FILES "${SRC_PATH}/${MAIN_FILE}.c"
"${SRC_PATH}/Interrupts.c"
"${SRC_PATH}/Utilities.c")
# Attempt to clear the other spurious compiler flags that I don't want,
# and which cause a compiler arguments error.
# This doesn't seem to work - the defaults still appear.
set(CMAKE_C_FLAGS_DEBUG "")
set(CMAKE_C_FLAGS_RELEASE "")
set(CMAKE_C_FLAGS_RELWITHDEBINFO "")
set(CMAKE_C_FLAGS_MINSIZEREL "")
# Compiler flags
set(CWARN "-Wl,-m,m68hc11elfb") # build for elf file and use memory.x for memory map
set(CTUNING "-mshort") # consider type int to be 16 bits
set(COPT "-Os") # turn on optimizer
set(CDEFS "-Dmc6811") # Add define to define the processor architecture for gel includes
set(CFILES "${MAIN_FILE}.c Interrupts.c Utilities.c")
set(CFLAGS "${CDEFS} ${COPT} ${CWARN} ${CTUNING} ${CFILES}")
set(CMAKE_C_FLAGS "${CFLAGS}")
# Project setup
include_directories(${INC_PATH} ${LIB_INC_PATH})
add_executable(${MAIN_FILE} ${SRC_FILES})
set_target_properties(${MAIN_FILE} PROPERTIES OUTPUT_NAME "${MAIN_FILE}.elf")
# Compiling targets
add_custom_target(main ALL ${OBJCOPY} -O binary "${MAIN_FILE}.elf" "${MAIN_FILE}.bin" DEPENDS ${MAIN_FILE})
add_custom_target(dump ALL ${OBJDUMP} -xDC --section=.text --section=.vectors "${MAIN_FILE}.elf" > "${MAIN_FILE}.dump" DEPENDS main)
set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${MAIN_FILE}.dump;${MAIN_FILE}.elf;${MAIN_FILE}.bin")
# Config logging
message("* ")
message("* Project Name:\t${PROJECT_NAME}")
message("* Project Source:\t${SRC_PATH}")
message("* Project Include:\t${INC_PATH}")
message("* Library Include:\t${LIB_INC_PATH}")
message("* ")
message("* Project Source Files:\t${SRC_FILES}")
message("* MAIN_FILE variable:\t${MAIN_FILE}")
message("* ")
message("* C Flags:\t${CMAKE_C_FLAGS}")
message("* ")
Here is the generated compilation command:
C:\GNUHC11\bin\m6811-elf-gcc.exe "-xc" "-Dmc6811" "-Os" "-Wl,-m,m68hc11elfb" "-mshort" "TestProgram.c" "Interrupts.c" "Utilities.c" "-IC:\\DEVELO~1\\source" "-IC:\\library\\gel-hc1x-1.6.1\\include" "-IC:\\library\\gel-hc1x-1.6.1\\include\\asm-m68hc11\\arch-32k" "-v" "-dD" "-E" "-D___CIDR_IGNORE_DEFINITIONS_START"
It would work but for the auto appended "-E" compiler flag at the end which I don't want. The other appended flags "-v" "-dD" and '-D___CIDR..." are also unwanted but do not cause a compilation error like "-E" does. How can I turn these appended flags off?
Thanks in advance for any help.
It seems you are cross-compiling, so the preferred cmake configuration is a bit different than normal.
See http://www.vtk.org/Wiki/CMake_Cross_Compiling for details, pay attention to the "toolchain file".
I have no idea regarding the auto-appended flags.
You can also have a look at the generated CMakeCache.txt file, either with any editor, from CLion itself, or with cmake-gui.
Remember that CLion copies your CMakeLists.txt in a funky temporary directory and runs cmake off the temporary directory, if you want to look at CMakeCache.txt by hand.
What I suggest is to put aside CLion while you are debugging the CMakeLists.txt, and just use cmake or cmake-gui directly from the shell.
Don't give up, both cmake and CLion are two very good programs IMHO :-)
There doesn't seem to be too much information on this one, but I also ran into this issue. In cmake if you do something like
target_compile_options(game PRIVATE /W4 /WX /wd4100 /wd4200 /wd4201 /FAs /EHsc /Gh /GH)
this will add those options for all compilers in that target.
You can use a generator if you want to add language specific options, so I changed it to:
target_compile_options(game PRIVATE
$<$<COMPILE_LANGUAGE:C>:/W4 /WX /wd4100 /wd4200 /wd4201 /FAs /EHsc /Gh /GH>)
which works.
Related
I am building a library (using Autotools) that looks like the following. The building of the library works fine when I add a *.cpp file to libmytest_la_SOURCES.
lib_LTLIBRARIES = libmytest.la
libmytest_la_SOURCES = test.capnp.c++
libmytest_la_CXXFLAGS = -I/usr/include -I$(top_srcdir)/src/includes
libmytest_la_LDFLAGS = -version-info 0:0:0 -L/usr/lib64
libmytest_la_LIBADD = -lcapnp
The problem is that I need to call a third-party compiler to generate code before doing the normal compile process. The following capnp tool will generate a c++ output file named test.capnp.c++.
capnp compile -oc++ test.capnp
And if I plug the output of that (test.capnp.c++) into the makefile above, my library is built. What I don't get is how to invoke that command into the Makefile.am to generate the needed source file and plug it into the libmytest_la_SOURCES variable.
Any thoughts?
Automake does not have direct support for capnp, and adding support for a new language or tool would involve hacking the program. But you can provide ordinary make rules in your Makefile.am file, and these will be carried through to the final generated Makefile. This is Automake's primary extension point.
Thus, you might add this to your Makefile:
test.capnp.c++ : test.capnp
capnp compile -oc++ $<
# or
# $(CAPNP) compile -oc++ $<
# where $(CAPNP) is the capnp binary as discovered by configure
You would want to also designate test.capnp as an additional file to distribute:
EXTRA_DIST = test.capnp
You should also consider whether you want the .c++ file to be included in distribution packages, to relieve the build-time dependency on capnp. If not, then instead of listing it in libmytest_la_SOURCES you should list it in nodist_libmytest_la_SOURCES, plus also in CLEANFILES:
#
# test.capnp.c++ is a built file that we choose not to distribute
#
nodist_libmytest_la_SOURCES = test.capnp.c++
CLEANFILES = test.capnp.c++
# or: CLEANFILES = $(nodist_libmytest_la_SOURCES)
Preferably when writing makefile, I'd like to utilise as much of the built-ins implicit rules as possible.
OUT := afile
OBJS := afile.o bfile.o cfile.o
# detect wsl
CC := # uses mingw-w64-gcc
LDFLAGS := # ...
LDLIBS := # ...
# end of wsl
$(OUT): $(OBJS)
The thing with Mingw-w64 is that it outputs afile.exe instead of plain afile. This is bad because now everytime I run make, afile.exe is being rebuilt. It would be really nice if Mingw-w64 isn't so stubborn with appending exe to my output file.
If I artificially append a custom extension, such as afile.rubbish, to the output file, the exe is dropped altogether. On the other hand, without any extension, Mingw-w64 forces appending the exe.
The implicit rule for linking objects is as follows, quoted from here:
n is made automatically from n.o by running the linker (usually called ld) via the C compiler.
The precise recipe used is ‘$(CC) $(LDFLAGS) n.o $(LOADLIBES) $(LDLIBS)’.
It will also do the right thing if there are multiple object files (presumably
coming from various other source files), one of which has a name matching that of the executable file.
Is there a way to change this exe appending behaviour to output file with Mingw-w64?
I'm trying to install the latest octave 3.8.1 from source in a cluster running redhat+IBM LSF. I don't have write access to anywhere else except my own home dir, that's why I have to install octave from source. The blas and lapack provided by the cluster does not work so I have to build them by myself. I have now finished compiling both blas and lapack and passed the ./configure, but when I run make, an error is reported as follows:
These are steps I used to build my own BLAS and LAPACK. The source of BLAS is in ~/src/BLAS while the source of LAPACK is in ~/src/lapack-3.5.0 and the source of octave 3.8.1 is in ~/src/octave-3.8.1.
With only two module, 1) pcre/8.33 2) acml/5.3.1/gfortran64, loaded, I compiled BLAS shared library using
gfortran -shared -O2 *.f -o libblas.so -fPIC
and static library using
gfortran -O2 -c *.f -fPIC
ar cr libblas.a *.o
Then I copy the shared library libblas.so to ~/src/octave-3.8.1. The contents of make.inc file in lapack's dir is:
####################################################################
# LAPACK make include file. #
# LAPACK, Version 3.5.0 #
# November 2013 #
####################################################################
#
SHELL = /bin/sh
#
# Modify the FORTRAN and OPTS definitions to refer to the
# compiler and desired compiler options for your machine. NOOPT
# refers to the compiler options desired when NO OPTIMIZATION is
# selected. Define LOADER and LOADOPTS to refer to the loader and
# desired load options for your machine.
#
FORTRAN = gfortran
OPTS = -shared -O2 -fPIC
DRVOPTS = $(OPTS)
NOOPT = -O0 -frecursive
LOADER = gfortran
LOADOPTS =
#
# Timer for the SECOND and DSECND routines
#
# Default : SECOND and DSECND will use a call to the EXTERNAL FUNCTION ETIME
#TIMER = EXT_ETIME
# For RS6K : SECOND and DSECND will use a call to the EXTERNAL FUNCTION ETIME_
# TIMER = EXT_ETIME_
# For gfortran compiler: SECOND and DSECND will use a call to the INTERNAL FUNCTION ETIME
TIMER = INT_ETIME
# If your Fortran compiler does not provide etime (like Nag Fortran Compiler, etc...)
# SECOND and DSECND will use a call to the INTERNAL FUNCTION CPU_TIME
# TIMER = INT_CPU_TIME
# If neither of this works...you can use the NONE value... In that case, SECOND and DSECND will always return 0
# TIMER = NONE
#
# Configuration LAPACKE: Native C interface to LAPACK
# To generate LAPACKE library: type 'make lapackelib'
# Configuration file: turned off (default)
# Complex types: C99 (default)
# Name pattern: mixed case (default)
# (64-bit) Data model: LP64 (default)
#
# CC is the C compiler, normally invoked with options CFLAGS.
#
CC = gcc
CFLAGS = -O3
#
# The archiver and the flag(s) to use when building archive (library)
# If you system has no ranlib, set RANLIB = echo.
#
ARCH = ar
ARCHFLAGS= cr
RANLIB = ranlib
#
# Location of the extended-precision BLAS (XBLAS) Fortran library
# used for building and testing extended-precision routines. The
# relevant routines will be compiled and XBLAS will be linked only if
# USEXBLAS is defined.
#
# USEXBLAS = Yes
XBLASLIB =
# XBLASLIB = -lxblas
#
# The location of the libraries to which you will link. (The
# machine-specific, optimized BLAS library should be used whenever
# possible.)
#
#BLASLIB = ../../librefblas.a
BLASLIB = ~/src/BLAS/libblas.a
LAPACKLIB = liblapack.a
TMGLIB = libtmglib.a
LAPACKELIB = liblapacke.a
Then I type make to compile LAPACK. After compilation, I copied the output liblapack.a to ~/src/octave-3.8.1.
The ./configure command line is:
./configure --prefix=$HOME/bin/octave --with-blas=./libblas.so --with-lapack=$HOME/src/octave-3.8.1/liblapack.a --disable-readline --enable-64
I can pass the ./configure. Then I type make to try to build octave 3.8.1 and I got the above error.
From the make.inc file it can be seen that I have followed the suggestion of the compiler "recompile with -fPIC" and modified the make.inc accordingly. I also add -shared switch in the OPTS variable. In addition, I have tried using old LAPACK version but not working. I really have no idea why the error still comes out. So I wonder if you could please tell me how to compile the LAPACK library so that it can be correctly used during installation of octave 3.8.1. The following two points may be worth considering. (1) should I compile lapack as a static library or a shared library? (2) should -fPIC switch be applied to lapack compilation or octave's make? If the latter, how to apply -fPIC to make? You don't have to get restricted to the above two points since there may be other reasons for the error. Any advice to solve this problem is welcomed. If you need any other information please tell me. Thank you.
Just compiled the lapack shared lib on my boss's beast... Here's a link which almost did it right.
I made some changes:
(1) Adding -fPIC to
OPTS & NOOPT in make.inc
(2) Change the names in make.inc to .so
BLASLIB = ../../libblas.so
LAPACKLIB = ../liblapack.so
(3) In ./SRC, change the Makefile from
../$(LAPACKLIB): $(ALLOBJ)
$(ARCH) $(ARCHFLAGS) $# $(ALLOBJ)
$(RANLIB) $#
to
../$(LAPACKLIB): $(ALLOBJ)
$(LOADER) $(LOADOPTS) -shared -Wl,-soname,liblapack.so -o $# $(ALLOBJ) ../libblas.so
Cuz lapack is calling blas, if you miss the very last part, your liblapack.so will fail! You need to LINK liblapack.so against libblas.so ( libatlas.so is also OK). You can use "ldd liblapack.so" to check its dependency. If you see libblas.so in there, pretty much you did it right.
(4) In ./BLAS/SRC, change the Makefile from
$(BLASLIB): $(ALLOBJ)
$(ARCH) $(ARCHFLAGS) $# $(ALLOBJ)
$(RANLIB) $#
to
$(BLASLIB): $(ALLOBJ)
$(LOADER) $(LOADOPTS) -z muldefs -shared -Wl,-soname,libblas.so -o $# $(ALLOBJ)
(5) I don't need libtmg.so so that I didn't change it...
Run
make blaslib
Then
make lapacklib
You will have both of them compiled. I check the liblapack.so with building a numpy on it and Python ctypes.cdll loading. All work for me to solve eigenvalues and eigenvectors... So it should be fine...
(6) YOU MAY NEED TO SET UP LD_LIBRARY_PATH to where you keep your library files.
google it... If not set by admin, then
export LD_LIBRARY_PATH=path-to-lib
If already set, then
export LD_LIBRARY_PATH=path-to-lib:$LD_LIBRARY_PATH
to overwrite your default libs.
So that you won't have ld linking errors. Good luck!!
In lapack-3.7.0, there are redundant lines in the SRC/Makefile. Simply deleting them will solve your error.
I would suggest using OpenBLAS.
> git clone https://github.com/xianyi/OpenBLAS.git
> make
> make make --PREFIX=INSTALL_DIR install
move the librabries from OpenBLAS to /usr/lib64
> cp /path/to/OpenBLAS/lib/* /usr/lib64/
then go to the octave installation path and run
> "your specific flags" ./configure "your specific arguments" --with-blas="-lopenblas"
I was wondering if there was any sample code for Makefiles (make) and CMakeLists.txt (cmake) that both do the same thing (the only difference being that one is written in make and the other in cmake).
I tried looking for 'cmake vs make', but I never found any code comparisons. It would be really helpful to understand the differences, even if just for a simple case.
The following Makefile builds an executable named prog from the sources
prog1.c, prog2.c, prog3.c and main.c. prog is linked against libmystatlib.a
and libmydynlib.so which are both also built from source. Additionally, prog uses
the library libstuff.a in stuff/lib and its header in stuff/include. The
Makefile by default builds a release target, but offers also a debug target:
#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 $#
%.o: %.cpp
$(CPP) $(CFLAGS) $(INCDIR) -fPIC $< -o $#
Here is a CMakeLists.txtthat does (almost) exactly the same, with some comments to underline the
similarities to the 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")
In this simple example, the most important differences are:
CMake recognizes which compilers to use for which kind of source. Also, it
invokes the right sequence of commands for each type of target. Therefore, there
is no explicit specification of commands like $(CC) ..., $(RANLIB) ... and so on.
All usual compiler/linker flags dealing with inclusion of header files, libraries, etc.
are replaced by platform independent / build system independent commands.
Debugging flags are included by either setting the variable CMAKE_BUILD_TYPE to "Debug",
or by passing it to CMake when invoking the program: cmake -DCMAKE_BUILD_TYPE:STRING=Debug.
CMake offers also the platform independent inclusion of the '-fPIC' flag (via
the POSITION_INDEPENDENT_CODE property) and many others. Still, more obscure settings can be implemented by hand in CMake just as well as in a Makefile (by using COMPILE_FLAGS
and similar properties). Of course CMake really starts to shine when third party
libraries (like OpenGL) are included in a portable manner.
The build process has one step if you use a Makefile, namely typing make at the command line. For CMake, there are two steps: First, you need to setup your build environment (either by typing cmake <source_dir> in your build directory or by running some GUI client). This creates a Makefile or something equivalent, depending on the build system of your choice (e.g. make on Unixes or VC++ or MinGW + Msys on Windows). The build system can be passed to CMake as a parameter; however, CMake makes reasonable default choices depending on your system configuration. Second, you perform the actual build in the selected build system.
Sources and build instructions are available at https://github.com/rhoelzel/make_cmake.
Grab some software that uses CMake as its buildsystem (there's plenty of opensource projects to choose from as an example). Get the source code and configure it using CMake. Read resulting makefiles and enjoy.
One thing to keep in mind that those tools don't map one-to-one. The most obvious difference is that CMake scans for dependencies between different files (e.g. C header and source files), whereas make leaves that to the makefile authors.
If this question is about a sample Makefile output of the CMakeList.txt file then please check the cmake-backend sources and generate one such Makefile. If it is not then adding to the reply of #Roberto I am trying to make it simple by hiding the details.
CMake function
While Make is flexible tool for rules and recipe, CMake is a layer of abstraction that also adds the configuration feature.
My plain CMakeLists.txt will look like the following,
cmake_minimum_required(VERSION 2.8)
project(example)
file(GLOB testapp_SOURCES *.cc)
add_executable(testapp ${testapp_SOURCES})
Note, that CMake hides how the build can be done. We only specified what is the input and output.
The CMakeLists.txt contains list of function-calls that are defined by cmake.
(CMake function) Vs Make rules
In Makefile the rules and recipes are used instead of functions . In addition to function-like feature, rules and recipes provide chaining. My minimalistic Makefile will look like the following,
-include "executable.mk"
TARGETS=testapp.bin
all:${TARGETS}
While the executable.mk will look like the following,
SOURCES=$(wildcard *.cpp)
OBJECTS=$(SOURCES:.cpp=.o)
DEPS=$(SOURCES:.cpp=.d)
%.bin:$(OBJECTS)
$(CC) $(CFLAGS) -o $# $^ $(LFLAGS) $(LIBS)
.PHONY: all clean
clean:
$(RM) $(OBJECTS) $(DEPS) $(TARGETS)
-include $(DEPS)
Starting from the scratch I shall start with a Makefile like the following,
all: testapp.bin
testapp.bin:sourcea.o sourcb.o
$(CC) $(CFLAGS) -o $# $^ $(LFLAGS) $(LIBS)
.PHONY: all clean
clean:
$(RM) $(OBJECTS) testapp.bin
I got this snippet from here and modified it. Note that some implicit-rules are added to this file which can be found in the makefile-documentation. Some implicit variables are also relevant here.
Note, that Makefile provides the detail recipe showing how the build can be done. It is possible to write executable.mk to keep the details defined in one file. In that way the makefile can be reduced as I showed earlier.
Internal Variables in CMake and Make
Now getting little advanced, in CMake we can set a compiler flag like the following,
set(CMAKE_C_FLAGS "-Wall")
Please find out more about CMake default variables in CMakeCache.txt file.
The CMake code above will be equivalent to Make code below,
CFLAGS = -Wall
Note that CFLAGS is an internal variable in Make, the same way, CMAKE_C_FLAGS is internal variable in CMake .
adding include and library path in CMake
We can do it in cmake using functions.
target_include_directories(testapp PRIVATE "myincludes")
list(APPEND testapp_LIBRARIES
mytest mylibrarypath
)
target_link_libraries(testapp ${testapp_LIBRARIES})
Vs adding include and library path in Make
We can add include and libraries by adding lines like the following,
INCLUDES += -Imyincludes
LIBS += -Lmylibrarypath -lmytest
Note this lines above can be generated from auto-gen tools or pkg-config. (though Makefile is not dependent of auto-config tools)
CMake configure/tweek
Normally it is possible to generate some config.h file just like auto-config tools by using configure_file function. It is possible to do more trick writing custom functions. And finally we can select a config like the following,
cmake --build . --config "Release"
It is possible to add some configurable option using the option function.
Makefile configure/tweak
If somehow we need to compile it with some debug flag, we can invoke the make like,
make CXXFLAGS=NDEBUG
I think internal variables, Makefile-rules and CMake-functions are good start for the comparison, good luck with more digging.
I am compiling a demo project.
The project is written for windows and linux. I have written a Makefile. However, I am not sure how to specify the platform the compiler will be compiling on.
I will be compiling on Linux.
In my source file I have this:
#if defined(WIN32)
#include ...
#include ...
#elif defined(LINUX)
#include ...
#include ..
#else
#error "OS not supported"
#endif
My simple Makefile is this. And when I compile I get the error "OS not supported".
How can I add the directive so that it will compile with the #elif defined(LINUX).
LIBS_PATH = -L/usr/norton/lib
INC_PATH = -I/usr/norton/include
LIBS = -lntr
app: *.cpp *.h Makefile
g++ $(LIBS_PATH) $(INC_PATH) *.cpp -o app
Many thanks for any suggestions,
Decide which is going to be your default platform - say LINUX.
LIBS_PATH = -L/usr/norton/lib
INC_PATH = -I/usr/norton/include
LIBS = -lntr
PLATFORM = -DLINUX
CXX = g++
app: *.cpp *.h Makefile
${CXX} ${CFLAGS} ${PLATFORM} ${INC_PATH} *.cpp -o $# ${LIBS_PATH} ${LIBS}
You can use round brackets in place of braces. This uses a macro for the C++ compiler, allows you to add other flags via CFLAGS (though that is also usually set by 'make'), and adds a platform, the include path, the library path and the actual library to the compile line.
Note that your rule enforces a complete recompilation of everything every time anything changes. This is 'safe' but not necessarily efficient. Note that wild-cards are dangerous too - more so for the source than the headers. You may include that backup copy of a file in the build (old-reader.cpp - you only wanted reader.cpp in there really). More conventionally, you list the object files needed for the program so that each object file can be individually rebuilt when needed, and the results linked together. If you get your dependencies correct (a moderately big 'if'), then there's no problem. If you get them wrong, you can end up with inconsistent programs.
However, if the difference is between a 5 second recompile and a 5 minute recompile, you should probably take the 5 minute recompilation (as shown) and answer another SO question while waiting.
To compile on Linux (64-bit):
make CFLAGS="-m64"
To compile on Linux (32-bit):
make CFLAGS="-m32"
To compile on Windows 64:
make PLATFORM=-DWIN64
To compile on Windows 32:
make PLATFORM=-DWIN32
Etc.
You can add -DLINUX=1 when compiling.
Also, if you run:
echo "" | cpp -dD
You can see the list of default #define when compiling. In linux, there will always be a:
#define __linux__ 1
in the output. So if you change your LINUX by the above #define, you don't need to do anything special. Ie:
...
#elif defined(__linux__)
...
As for the Makefile itself, I would do something like:
CXX=g++
CPPFLAGS = -I/usr/norton/include
LDFLAGS = -L/usr/norton/lib -lntr
OBJ_FILES = one.o two.o
app: $(OBJ_FILES) Makefile
one.o: one.cpp one.h
two.o: two.cpp two.h
So the implicit rules are used.