In my c/c++ files, there are multiple #define. As an example:
#ifdef LIBVNCSERVER_HAVE_LIBZ
/* some code */
#ifdef LIBVNCSERVER_HAVE_LIBJPEG
/* some more code */
Can you please tell me how can I modify my Makefile.in so that I have those #define in ALL files during compilation?
Thank you.
-DLIBVNCSERVER_HAVE_LIBZ -DLIBVNCSERVER_HAVE_LIBJPEG
You could pass those in CPPFLAGS,
CPPFLAGS = -DLIBVNCSERVER_HAVE_LIBZ -DLIBVNCSERVER_HAVE_LIBJPEG
or make new variable
CUSTOMDEFINES = -DLIBVNCSERVER_HAVE_LIBZ -DLIBVNCSERVER_HAVE_LIBJPEG
and pass it to CPPFLAGS = -DEXISTINGFLAGS $(CUSTOMDEFINES)
Those are finally will pass to gcc/g++ -D...
$(CC) $(CPPFLAGS)
Add the line below, to your makefile:
DEFINES=LIBVNCSERVER_HAVE_LIBZ LIBVNCSERVER_HAVE_LIBJPEG
...
... further on in your makefile on the line where it says ....
...
$(cc) ($(addprefix -D, $(DEFINES))) .....
...
...
This is to serve as an example, you only add another define to the DEFINES variable which gets referenced on the line as shown $(cc) -D$(DEFINES) in which the make will automatically expand the variable and compile those that are #ifdefd.
Thanks to R Samuel Klatchko for pointing out a small amiss...this is specifically for GNU's make, you can use addprefix do properly do that ($(addprefix -D, $(DEFINES))).
Don't modify your Makefile.in. (and consider using Automake and converting your Makefile.in to a much simpler Makefile.am). The whole point of those #defines is to let the configure script define them in config.h, and your source files should #include <config.h>. If you are maintaining the package, you will need to write tests in configure.ac to determine whether or not the system being used has libvncserver installed with jpeg and zlib support. If you modify Makefile.in to always define them, then you are making the assumption that your code is only being built on machines where those features are available. If you make that assumption, you should still add checks to configure.ac to confirm it, and have the configure script fail if the dependencies are not met.
Related
I am new to makefiles and am struggling a little bit to get things to work how I want.
I have a header file with some structs and a bunch of macros that I have sitting in #ifndef statements so that they have a default value if they're not defined on the command line.
I have three .c files that all include this header to make use of these macros.
In my makefile, I need to be able to compile all my source files, which have the header file as a dependent.
What I would like to be able to do is when I run make, if I include new values for those macros, that the header file is updated, and this triggers the source files to also be recompiled so that they include the new values.
I don't know if this is the correct way to go about it. The issue I am trying to avoid is if I pass these new values, but say only one of these source files recompile because make only identifies it as having been changed, and therefore different values are being used across the three programs.
What I would like to be able to do is when I run make, if I include new values for those macros, that the header file is updated, and this triggers the source files to also be recompiled so that they include the new values.
And how do you suppose that make would recognize that the macro definitions in use have changed? It cannot very easily compare the definitions themselves to values as-of previous runs.
What make can do pretty easily is compare the timestamp of the file wherein the macro definitions are recorded to the timestamps of the object files. It can do that by making the former file a prerequisite for each of the latter files.
The file containing the macro definitions might be the makefile itself or some file included into it. If you use the makefile itself then you will sometimes get recompilations for reasons other than the macro definitions having changed, but many of those reasons will in fact be good reasons. The object files and binaries have a bona fide dependency on the instructions used to build them.
So you might have something along these lines:
SOURCES = larry.c curly.c moe.c
OBJECTS = $(SOURCES:.c=.o)
DEFINES = -DOPTION1=1 -DOPTION2=0 -DOPTION3=1
prog: $(OBJECTS)
$(CC) -o $# $^
%.o: %.c stooges.h Makefile
$(CC) -c -o $# $(DEFINES) $<
It would possible to instead use a similar procedure update the timestamp of the header file, thus forcing recompilation indirectly, but that's synthetic. I recommend expressing the true dependencies instead.
OR, for a single-developer project, it would probably be feasible to just make it a developer responsibility to manually perform a clean build after performing makefile updates that require it. That scales poorly as you add developers, though.
I have an AVR8 GCC application that can be built with a standard makefile. Because some folks who want to build the application don't want to set up make and such (or have trouble doing so), I also have figured out how to set the project up so it can be compiled from the Arduino IDE as well.
All is working.
But, I normally set some items in the makefile, like the version number and such, but creating the VERSION string in the makefile and passing it as a define into each source file compilation. But, when run from the Arduino IDE, that step is obviously not occurring. So, I have to create a second #define in the Arduino sketch stub to recreate the define.
This means when I update the version, I need to do so in 2 places, in the makefile and in the source file.
The easy option is to simply move the VERSION creation to the source file, where both can use it. And, I'm OK doing that, but
The makefile actually needs the version information, both to create the right filename (think app_v1.2.3.4.bin) and embed the version number into the bin file since it is used by the boot-loader (if requested) to ensure the version the boot-loader flashes is newer than the one already in FLASH. So, if I move the VERSION, RELEASE, MODIFICATION, etc. defines into the C code, I need to find a way to pull them back into the makefile.
I tried using the file read operations in the makefile, but they seem to ignore:
#define VERSION 0
with the prefaced '#' char.
I see there's some options to run sed/awk/etc, in bash, but I don't want to make too many assumptions on the environment, and the makefile currently runs on Windows as well as Unix/Linux without any differences.
I tried a few stack overflow examples, but nothing seems to yield those 4 numbers from any file, .h or otherwise.
I'm OK with creating version.h with just:
#define VERSION 0
#define RELEASE 1
#define MODIFICATION 2
#define FIX 4
If I can read it into the makefile and create the variables I need.
Jim
You may take a look at gmtt which was designed exactly with you use case in mind. In gmtt the following should read and analyze your header file:
include gmtt.mk
# create a 3-column table from the header file. The first column is just the "#define"
VNR_TABLE := 3 $(file < version.h)
# Extract the values from the table: select column 3 from VNR_TABLE where column 2 equals a string constant.
# Be careful not to introduce spaces in the compare!
VER := $(call select,3,$(VNR_TABLE),$$(call str-eq,$$2,VERSION))
REL := $(call select,3,$(VNR_TABLE),$$(call str-eq,$$2,RELEASE))
MODF := $(call select,3,$(VNR_TABLE),$$(call str-eq,$$2,MODIFICATION))
FIX := $(call select,3,$(VNR_TABLE),$$(call str-eq,$$2,FIX))
I couldn't test it but I think you get the idea.
PS: using a GNUmake library just means placing the included file alongside the makefile.
I think in this case you can use the ‘file’ function of makefiles.
It allows you to write (with > specifier) or read (with < specifier) to/from files. Then you can trim (with filter-out) your variables inside your makefile.
Source: https://www.gnu.org/software/make/manual/html_node/File-Function.html#File-Function
You can use GNU make's $(shell ...) function to extract the macro expansions. Assuming VERSION is defined in src.c and tokens are delimited by spaces (not tabs):
VERSION := $(shell sed -n -e "s/^\#define VERSION *\(.*\)/\1/p" src.c)
.PHONY: all
all:
#echo VERSION=$(VERSION)
Reading the official documentation
A prerequisite is a file that is used as input to create the target. A
target often depends on several files.
If my source file already includes the header, should I list the header in the rule?
src.c
#include <stdio.h>
#include "myheader.h"
int main()
{
printMessage();
return 0;
}
myheader.h
void printMessage()
{
printf("a message to screen\n");
}
makefile
src : src.o
cc -o src src.o
src.o : src.c
cc -c src.c
If I add myheader.h in the prerequisite it changes nothing, the same message is printed to screen. If a header is explicitly included, should it appear in the prerequisite?
The header file should be included in the dependency list.
The first time you use make to build your program, it will compile just the same whether you include myheader.h as a dependency or not. The difference is what happens when one of the files changes.
If you run make again without changing anything, it will say that "src" is up to date and won't compile anything. However, if you were to modify myheader.h and you didn't include it as a dependency, then make will say that the target is up to date. It doesn't look at the source file to see what files it includes. The make utility doesn't know anything about C or C++ source code (or any other source code). It looks only at whether the given files have changes without looking at their content.
When you include myheader.h as a dependency, if you later modify that file then running make will rebuild the program.
If you want to know all the non-system header files that a given source file depends on, you can run gcc with the -MM option. This will output a make rule listing the header dependencies of a source file.
For example, if you run gcc -MM src.c, you'll get the following output:
src.o: src.c myheader.h
You can then include that in your makefile.
Yes, you should.
The make program uses the list of files to figure out if a dependency changed and the the target should be rebuilt as a result. It needs you to specify that dependency explicitly.
It does not see the inclusion, it only sees the rules you specified. So there is a theoretical possibility that you change the header in a way that may require a re-compilation of src.o, but make will not know you did that unless you tell it to watch out.
In order to improve the aesthetics of some code, I would like to have a .h file contain some code that sets a #define based on which file the .h file is included from. For example
#if (__file__ == "main.c")
#define MOUDLE MODULE_MAIN
#elif (__file__ == "foo.c")
#define MODULE MODULE_FOO
#endif
Is there any way to accomplish something like this? The main motivation is to avoid putting a #define MODULE at the top of every file and instead have one location where the mapping is defined and to just include the same .h file.
No, you can't do this. #if can only do integer expressions. It knows nothing about strings or how to compare them.
What you want is not possible with the standard C preprocessor. Check by reading the C standard, eg n1570, or some C reference, or the wikipage on the C preprocessor, or the GNU cpp manual.
But consider another way to achieve the same: configure appropriately your build automation.
For example, if you use make, then edit your Makefile appropriately. How to do that is a very different question.
You could have a rule for make which passes a specific -DMODULE=name to gcc
For example in my bismon (on github) the Makefile has near line 141 something similar to
modules/modbm_%.so: modules/modbm_%.c bismon.h $(GENERATED_HEADERS) $(BM_HEADERS)
$(CCACHE) $(LINK.c) -fPIC \
-DBISMON_MODID=$(patsubst modules/modbm_%.c,_%,$<) -shared $< -o $#
Be creative. The build machinery is part of your source code. Adapt it to do what you want. Don't expect the standard preprocessor to cover all your needs. Learn how to invoke GCC (or your favorite compiler) on the command line. In some cases, it is even worthwhile to generate some C file (perhaps some header file), and you might use another preprocessor (like GPP or m4) for that purpose.
Remember that the compiler (notably GCC and Clang) is a command line program, that you should drive from something else (like make, ninja or many other build automation tools).
(even on microsoft systems the compiler is still a command line thing, but that fact is often ignored)
BTW, I dislike many IDEs because they are hiding the build process, and you need to master it. So you need to configure it (e.g. by writing your Makefile or something else) and to understand and tailor it.
The main motivation is to avoid putting a #define MODULE at the top of every file and instead have one location where the mapping is defined
That single location defining such a mapping should probably be your build infrastructure (e.g. your Makefile if using make); you'll adapt it to invoke gcc or clang (or most other C compilers) with an appropriate -DMODULE=name flag. (BTW, you also want the convention that your base name of sources files are C identifiers, so you won't have any a-1.c file -since a-1 is not an identifier-, but a bcde.c one).
If using GNU make, read its documentation, then run make -p to understand the rules (both builtin, and custom) relevant to your case. Then consider perhaps a rule similar to:
%.o: %.c $(YOURHEADERS)
$(COMPILE.c) -DMODULE=$(patsubst %.c,MODULE_%,$^) -c $< -o $#
but adapt that rule to your needs. (you could need some $(shell ... ) inside it if your file names are lower cases, and you want upper case MODULE).
BTW, you could also generate parts of your Makefile (or have some generated C files, which you would #include appropriately).
What should appear in Makefile.am, configure.ac and the source to link a library to a program with Autotools?
My (currently trivial) project configures, builds and runs OK, but I want to tidy it up.
I currently have configure.ac:
dnl Process this file with autoconf to produce a configure script.
AC_PREREQ(2.59)
AC_INIT(foo, 1.0)
AC_CANONICAL_SYSTEM
AM_INIT_AUTOMAKE()
AC_PROG_CC
AC_CONFIG_FILES(Makefile src/Makefile)
AC_OUTPUT
PKG_CHECK_MODULES([DEPS], [apr-1 >= 1.4.2])
Makefile.am (in src/):
bin_PROGRAMS=a.out
a_out_SOURCES=foo.c
a_out_LDADD = /usr/lib/libapr-1.so
and foo.c:
...
#include <apr-1.0/apr_general.h>
#include <apr-1.0/apr_pools.h>
...
I want to get rid of the hard-coded path to /usr/lib/libapr-1.so in Makefile.am and the relative #include paths in foo.c. I'm making a big assumption that PKG_CHECK_MODULES can find and tell me the locations of the files associated with libapr.
How should I modify these files to make this work?
Thanks,
Chris.
Check out this tutorial.
The interesting part is if you define your pkg check like this:
PKG_CHECK_MODULES([APR], [apr-1 >= 1.4.2])
you can then use it in Makefile.am:
project_name_LDADD = $(APR_LIBS)