What is the CMake equivalent of the GCC -c option? - c

For example, if I had a makefile that contains this:
dynArray.o: dynArray.c dynArray.h type.h
gcc -Wall -ansi -c dynArray.c
How would I translate that into a CMakeLists.txt file?

Probably CMake's object libraries would do that, that mean compile objects but not archive them like normal library would.
add_library(<name> OBJECT <src>...)

Since an object file alone is not the end result of what you are building, I suspect there is more context to the question that is missing. You are probably building an executable from the objects. Just use add_executable to specify your target and the source files that make up the target. Then use target_compile_definitions to specify the compile options you want while compiling source files for that target. For example:
add_executable(dynArray dynArray.c dynArray.h type.h)
target_compile_definitions(dynArray PRIVATE -Wall -ansi)
You can verify that the resulting compile commands are what you expect by using the Unix Makefiles generator and passing VERBOSE=1 to the make command:
mkdir build; cd build
cmake -G "Unix Makefiles" ..
make VERBOSE=1
This will cause the generated Makefile to display the full command lines used on every step of the build.

Related

Using readline statically in C (compilation and linkage)

I would like to link readline statically with my program and I found this page about readline compilation from source http://www.bioinf.org.uk/software/profit/doc/node17.html but I'm a bit confused about the process.
The page talks about a variable READLINELIB in the makefile but I don't find it.
Could someone show me the way to use readline statically in my program, what to put in my Makefile for compiling readline from source and link it with my program?
Thank you.
Finally I figured out the proper way to do it, I using the --prefix option of the configure file I can tell where to put/install the library. The problem about installation was that I don't have the right to access other directories than my $HOME, so no problem doing this:
configure --prefix=$HOME/libreadline && make && make install-static
Then in my program I include the file from $HOME/libreadline/include.
To compile the main program I link the program with the archive libraries $HOME/libreadline/lib/libreadline.a and $HOME/libreadline/lib/libhistory.a.
Also since readline files uses directive like #include <readline/readline.h> which doesn't correspond to the location of the files, I must tell the compiler where to look for included files. To do this, before running gcc, I set the variable C_INCLUDE_PATH to $HOME/libreadline/include.
Finally, since readline uses ncurses dynamic library I must tell the compiler to dynamically link it with my program. It might be the case of termcap too...
The overall process looks like:
configure --prefix=$HOME/libreadline && make && make install-static
export C_INCLUDE_PATH=$HOME/libreadline/include
gcc -o myprogram myprogram.c $HOME/libreadline/lib/libreadline.a $HOME/libreadline/libhistory.a -lncurses -ltermcap
I was confused about what make install do, it only copy files to the location provided by the configure, by default it installs in system directories like /usr/include, etc... but providing the --prefix option make install will copy all files in the specified directory.
Installation is just copying compiled program, libraries, doc, etc to a certain location, by default standart system directories, if you don't have access to those directories like me you could "install" it in your own directory and then do whatever you wan't with it.
I could have installed the dynamic library instead the static one, but then I would have to modify the LD_LIBRARY_PATH environment.
get readline source
wget http://git.savannah.gnu.org/cgit/readline.git/snapshot/readline-master.tar.gz
tar zxvf readline-master.tar.gz
cd readline-master/
examples folder does not have Makefile, which is generated using Makefile.in script.
following steps build static & dynamic libs & puts them inside /usr/local/bin
./configure
make
sudo make install
may have to install curses as "sudo apt-get install libncurses5-dev"
Use following make file (strip down version from examples folder)
(Make sure tab is honored otherwise makefile will not work)
RM = rm -f
CC = gcc
CFLAGS = -g -O
INCLUDES = -I/usr/local/include
LDFLAGS = -g -L/usr/local/lib
READLINE_LIB = -lreadline
TERMCAP_LIB = -ltermcap
.c.o:
${RM} $#
$(CC) $(CFLAGS) $(INCLUDES) -c $<
SOURCES = rlversion.c
EXECUTABLES = rlversion
OBJECTS = rlversion.o
all: $(EXECUTABLES)
everything: all
rlversion: rlversion.o
$(CC) $(LDFLAGS) -o $# rlversion.o $(READLINE_LIB) $(TERMCAP_LIB)
clean mostlyclean:
$(RM) $(OBJECTS) $(OTHEROBJ)
$(RM) $(EXECUTABLES)
rlversion.o: rlversion.c
I was in need of libraries libreadline.a, libhistory.a for both 64 and 32 bit versions.
The answer provided by Rajeev Kumar worked for me. ( Had a little trouble finding and installing libncurses).
For 32-bit versions, using https://packages.ubuntu.com/search?keywords=lib32readline-dev, the following command worked for me.
sudo apt install lib32readline-dev
So it is hoped that for 64 also, it works
sudo apt install libreadline-dev

Makefile order, doesn't compile everything

I have a makefile with this simple rules,
ref_approx_bs2_rsq_5_10_1ulp_arch1 : ref_approx_bs2_rsq_5_10_1ulp_arch1.o
gcc -I../CModels -L../CModels -std=c99 -o ref_approx_bs2_rsq_5_10_1ulp_arch1 ref_approx_bs2_rsq_5_10_1ulp_arch1.o -lm -limg_float
ref_approx_bs2_rsq_5_10_1ulp_arch1.o : ref_approx_rsq.c ../CModels/cogen_fp_bs2_rsq_5_10_1ulp_arch1.cpp ../CModels/cogen_fp_bs2_rsq_5_10_1ulp_arch1.h ../CModels/img_float.h ../CModels/img_float.c
gcc -DCMODELLOC=\"../CModels/cogen_fp_bs2_rsq_5_10_1ulp_arch1.cpp\" -DCMODEL_NAME=cogen_fp_bs2_rsq_5_10_1ulp_arch1 -std=c99 -o ref_approx_bs2_rsq_5_10_1ulp_arch1.o -c ref_approx_rsq.c
libimg_float.a : ../CModels/img_float.o
ar -rcs ../CModels/libimg_float.a ../CModels/img_float.o
img_float.o : ../CModels/img_float.h ../CModels/img_float.c
gcc -I ../CModels/ -o ../CModels/img_float.o -c ../CModels/img_float.c
But basically if I modify img_float.c and try to use the make file again it doesn't compile and create libimg_float.a.
The makefile itself looks correct to me since I've written all the prerequisites.
Any suggestion?
It won't recompile libimg_float.a because nothing depends on it.
Make doesn't go through your makefile and always try to rebuild every target. Make works by finding the first (explicit) target listed and trying to build that. Before building the first target, it will try to build all the prerequisites of that target, and before that it will try to build all the prerequisites of those targets, etc. until no more prerequisites are found.
If there is a target which is not a prerequisite of the first target (or its prerequisites, etc.) then it will not be built, by default. You can request that it be built by listing it on the command line: make libimg_float.a will tell make to build that target, instead of the first explicit target. Of course you can list lots of targets on the command line.
But generally people create one target first, commonly called all, which lists all the targets that should be built by default as a prerequisite.
Here, though, your makefile is not right because your ref_approx_bs2_rsq_5_10_1ulp_arch1 target does use libimg_float.a, but it's not listed as a prerequisite. That means it won't be updated when libimg_float.a is out of date. You should change your makefile to show that prerequisite relationship:
ref_approx_bs2_rsq_5_10_1ulp_arch1 : ref_approx_bs2_rsq_5_10_1ulp_arch1.o libimg_float.a

Using Makefile to link multiple files

I'm kind of lost in the Makefile business and I'm trying to come to terms with it. I would love if someone could make it clear on an example I'm currently programming.
I have these files:
my-bit-vector.h -> a header file included in eratost.c, ppm.c
ppm.c -> a .c file which includes my-bit-vector.h and error.h
error.h -> a header file included in eratost.c, ppm.c
error.c -> a .c file which includes error.h and defines the functions in it
erato.c -> a .c file which includes my-bit-vector.h and error.h
I need to link these together into one executable file. How would I go about doing that via Makefile? I hope I didn't forget something. Could you please help?
The contents of a Makefile, when put simple, is one or more targets (the things you want built). Each target has dependencies (if any dependencies don't exist yet, they must be built, and if they do exist but they're newer than their target, the target must be rebuilt), and rules (the commands to build the target, presumably from the dependencies).
In your case, lets say your final output is a program called program. You've identified the sources to build it, but you don't build an executable directly from sources, you do it from object files. You could start your makefile like this:
program: ppm.o error.o erato.o
cc -o program ppm.o error.o erato.o
WARNING The spacing on rule lines (the cc command line shown above) requires a TAB, not just spaces!
That's enough to start but not enough to be right. You'll notice that there's no target:dependency/rules for the .o's yet, but it still works because Make has some built-in rules.
With this makefile, if you type "make" twice, the first time you'll see everything gets built and the second time it won't -- nothing changed so no rebuild is needed. Unfortunately if you edit your .h's now, the .c's still won't rebuild, so lets fix that:
program: ppm.o error.o erato.o
cc -o program ppm.o error.o erato.o
ppm.o: ppm.c my-bit-vector.h error.h
error.o: error.c error.h
erato.o: erato.c my-bit-vector.h error.h
Now you've got your dependencies set to cause make to rebuild sources that must be rebuilt when headers change. There's no rules on those source builds because the built-in rule here is (often) sufficient. You can override the built-in if necessary, of course.
Here, when you type "make", the tool will find the first target (program) and inspect its dependencies. It will then make sure each of its dependencies are up to date (based on their target:dependency / rule definitions), recursively as long as there are targets needing to be considered for being built. Finally it will apply the rules for this target to complete its build.
There's much more that can be done with makefiles, this is just a brief intro.
program: ppm.o error.o erato.o
gcc ppm.o error.o erato.o -o program
ppm.o: ppm.c
gcc -c ppm.c -o ppm.o
error.o: error.c
gcc -c error.c -o error.o
erato.o: erato.c
gcc -c erato.c -o erato.o
stuff before the ":" is the target. stuff after ":" are the required targets for this target.
So if you "make program" make is looking for a target named "all". The target all requires ppm.o which is also defined as target in the makefile. So it executes this target first. the target ppm.o requires ppm.c which has no target defined in the makefile, so it is probably a file. I hope this explains the basic functionality to you.
http://mrbook.org/tutorials/make/
is a really good tutorial for beginners, with some basic makefile examples.

How do I add my own header file directory to Mac Terminal gcc?

I'm trying to compile a C program (myProgram.c) that includes a custom .h file that is in a specified directory. How can I add the directory to gcc so that I can build myProgram.c anytime using just a command like gcc myProgram (with no flags and what not)
You can do this by altering the C_INCLUDE_PATH environment variable, e.g.
C_INCLUDE_PATH=~/include
export C_INCLUDE_PATH
You can add that to your .bashrc or .bash_profile or whatever to always have the environment variable set properly. Here's a reference on how you can do the same for libraries and C++.
had to use a whole set of flags to get this working on El Capitan:
export DYLD_LIBRARY_PATH=/usr/local/include
export CPPFLAGS="-I/usr/local/include/snappy-c.h"
export CFLAGS="-I/usr/local/include/snappy-c.h"
export CXXFLAGS="-I/usr/local/include/snappy-c.h"
export LDFLAGS="-L/usr/local/lib"
Makefiles would be helpful in this situation, they ease the compilation of multiple file projects.
Assuming you are using these same files and they are in the same directory
main.c
custom.c
custom.h
A sample makefile could look like
all: main.o custom.o
gcc main.o custom.o -o myExecutable
main.o: main.c
gcc -c main.c
custom.o: custom.c custom.h
gcc -c custom.c
clean:
rm -f *.o myExecutable
Or something similar, the general format is
name: dependency
command
So by running make all from the commandline you would be instructing the compiler to compile your source code into object files, and then link those object files together into an executable.
Make should be easily available on any modern system. For more information on basic makefiles and usage refer to this simple tutorial: http://mrbook.org/tutorials/make/

how to add a library to 'make' command in c

This is the header file and its C file:
cs50.h and
cs50.c
Now I use them in the following example http://www.paste.ubuntu.com/576370/ — which is no longer available.
I already put the header file in /usr/bin/include or something like that and when I try to compile my code using gcc -o xxx xxx.c, it doesn't work, so tried to fix this and the following way worked: http://www.paste.ubuntu.com/576371/ — which is no longer available.
Now I want to do something to make the 'make' command work as the gcc does.
What do I need to do?
The following was the old topic:
I was using gcc command to
compile C programs but after a period
of time I got a problem. I need
to compile a new header file and use
it as a library.
The header file called cs50.h.
so after doing it and it's ok I can
compile using the following
gcc -o xxx xxx.c -lcs50
It works but now I want to use 'make'
command and I can't get it to work.
It just don't compile the header file
and library as gcc was before I edit
it to accept the cs50 library.
So now I want to add to the 'make'
command the following: -lcs50
Can anyone help me in this please?
Near the top of your Makefile, add the line:
LDLIBS = -lcs50
If you are using Make's default (implicit) rules for the building, then that is all you need to do. If you are using explicit rules, you will need to add $(LDLIBS) to your explicit rules.
If there is no Makefile, then make is using default rules, and you can either just create a makefile with
echo LDLIBS = -lcs50 > Makefile
or tell make to link with certain libraries by specifying the required libraries in LDLIBS in the environment. For example, if you are using a sh-derived shell (anything other than csh or tcsh) you can do:
LDLIBS=-lcs50 make target
If you are using a csh variant, you can do:
env LDLIBS=-lcs50 make target
or just do (again, for non-csh shells)
export LDLIBS=-lcs50
before running make. (For csh variants, do setenv LDLIBS -lcs50)
You can use below “make” command to link library and include header directories,
make <.c or .cpp source filename_without_extension> LDLIBS="-l<lib1> -l<lib2>"
suppose you have server.cpp file to compile using make command,
make server LDLIBS="-lcpprest -lpthread -lssl -lcrypto" LDFLAGS="-L/usr/lib/" CXXFLAGS="-I/usr/include/"
Output will expand the compilation command as,
g++ -I/usr/include/ -L/usr/lib/ server.cpp -lcpprest -lpthread -lssl -lcrypto -o server
Did you forget that you have to tell gcc in what directory the CS50 library is located?
gcc … -L/directory/for/cs50_library -lcs50

Resources