moving from make to cmake: how to use build target with wildcards - makefile

I'm trying to convert an makefile-build to cmake (to avoid the current state of being forced to take care for the windows-build env based on make/msdev and the linux based on make/gcc).
In this project, I've found a directory full of sourcecode files that get, based on a naming convention, compiled to libraries. (e.g. c1223.c => c1223.dll (or .sl) )
The current makefile consists of some directives using wildcards, e.g.:
LIB_NO = $(basename $(subst s,,$#))
OBJ = $(OBJ_PATH)/s$(LIB_NO).o $(OBJ_PATH)/c$(LIB_NO).o\
$(OBJ_PATH)/b$(LIB_NO).o
$(OBJ_PATH)/%.o : %.c
-$(CC) $(CFLAGS) -I$(PWD) -c $< -o $#
-(chmod a+w $#;true)
I've searched for a while but can't find anything that seems to work. Is it even possible with cmake to let it generate a wildcard based build?
Any comments, hints and suggestions are very welcome :)
cheers
Markus

You can use fairly primitive globbing (there's no regular expression syntax that I can see).
file(GLOB TESTSRCS "test/src/*.cpp")
# Compile the test sources.
add_executable(Tests ${TESTSRCS})
target_link_libraries(Tests ${LIB} gtest gtest_main)
The actual makefiles do not seem to contain wildcard searches inside them. If you add new files you will need to re-run cmake.
What I don't know is how you would manage to wrap up the library creation in a single macro if you have many different library files to generate.
You might be able to do something like this if there's only one c file per library:
file(GLOB libfiles "path/to/libs/c*.c")
foreach(libfile ${libfiles})
GET_FILENAME_COMPONENT(libname ${libfile} NAME) # remove the '.c' part (untested, hopefully this will work)
add_library(${libname} ${libfile})
endforeach(libfile)
If anybody else has a better solution, I would also like to learn it.

CMake does not generate makefiles that have wildcard-based rules in them. It generates specific rules for the files that it knows about.
In your example, you are explicitly listing the .o files that comprise your library. In CMake, you would instead explicitly list the source files that contribute to your library, and then let CMake take care of the rest.
Do you need makefiles that have wildcard-based rules in them for some reason?
Couldn't you simply construct a list of the source files, and then, for each element in the list, do an "add_library" call with the source file and a library name constructed from the source file name?

Related

How to use GNU make to update files in all subdirectories containing a particular file?

In my project, I have a set of sub-directories that contain package.yaml files, for e.g.:
A/package.yaml
B/package.yaml
C/package.yaml
If I run hpack A/package.yaml, the file A/A.cabal is (re-)generated. The list of such directories can change over time, so I want to use GNU make to find all immediate sub-directories containing package.yaml files and generate the corresponding .cabal files using hpack.
I tried this based on another question, but it didn't work:
HPACK_FILES := $(wildcard */package.yaml)
PKG_DIRS := $(subst /,,$(dir $(HPACK_FILES)))
CABAL_FILES := $(addsuffix .cabal,$(join $(dir $(HPACK_FILES)),$(PKG_DIRS)))
test:
#echo $(CABAL_FILES)
update-cabal: $(CABAL_FILES)
%.cabal: package.yaml
hpack $<
However, make update-cabal says there's nothing to be done. make test however does output the right cabal files. How can I fix this?
Cheers!
The problem is this:
%.cabal: package.yaml
There is no file package.yaml. The files are named things like A/package.yaml. That is not the same thing.
Because the prerequisite doesn't exist, make decides that this pattern rule cannot match and so it goes looking for another rule that might be able to build the target. It doesn't find any rule that can build the target, so make says there's nothing to do because all the output files already exist.
Unfortunately what you want to do is not at all easy with make, because make is most comfortable with input and output files that are tied together by the filename with extensions, or similar. And in particular, it has a really hard time with relationships where the variable part is repeated more than once (as in, A/A.cabal where the A is repeated). There's no easy way to do that in make.
You'll have to use an advanced feature such as eval to do this. Something like:
# How to build a cabal file
%.cabal:
hpack $<
# Declare the prerequisites
$(foreach D,$(dir $(HPACK_FILES)),$(eval $D/$D.cabal: $D/package.yml))

Makefile to compile Fortran source files in different directories

Here is my problem: I have been using Java for many years and enjoy having many directories separating different areas of the code. For my current project I am writing Fortran code, which should compile under Windows and Unix/Linux. For Windows, I am using Eclipse/Photran with MinGW/gfortran tools to set up Makefiles.
Here is the desired project structure (deep nesting tree-like Java-like would be even nicer)
dir1/src/*.f95
dir1/make/Makefile_lib1.any
dir1/make/Makefile_lib1.win
dir1/make/Makefile_lib1.unix
dir2/src/*.f
dir2/make/Makefile_lib2.any
dir2/make/Makefile_lib2.win
dir2/make/Makefile_lib2.unix
...
dir_main/src/*.f or *.f95
dir_main/make/Makefile_main.any
dir_main/make/Makefile_main.win
dir_main/make/Makefile_main.unix
I would like to call make Makefile_main.unix, which would set up any Unix-specific variables and then include Makefile_main.any, Makefile_lib1.any, ...
(similar for making on Windows)
I got to the stage where I can see all source files in a given directory, e.g.
SRCS := $(wildcard $(SRC_DIR)/*.$(SRC_EXT))
Now I am struggling with how to make all dependencies as in Fortran 95 each source generates *.o and *.mod.
Is there a way to switch between directories when compiling so that all targets/dependencies do not have dir-path in their names? Note that I am calling make from some other service directory where the Eclipse project lives. Any suggestions how to proceed?
I really do not want to do the usual Fortran style of having just one directory with
all the mess together with the code.
There are two major strategies you can take.
You can place a makefile in each subdirectory and have it support targets like all, clean etc, then use recursive make invocations from the top-level makefile to make the same target (e.g. all) in every subdirectory.
Alternatively, you can handle it all in one make invocation, without recursing, but then you'll have to work with relative paths containing subdirectory names. Personally I don't see a problem with it, and I've maintained a system of makefiles based on this approach.
Here is what you can do in your case, assuming that SRC is set correctly to the list of relative paths to every source you need to compile.
# This replaces the SRC_EXT suffix with .o in each filename
OBJ = $(SRC:%.$(SRC_EXT)=%.o)
$(BINARY_NAME): $(OBJ)
...link command...
%.o: %.$(SRC_EXT)
...compile command...

Make and VPATH. Why are my source files being placed where I don't want them?

I am trying to compile with make. I have source in two directories, src and altsrc. I want make to look in altsrc for source files first, and then in src. I want the objects to go into directory obs. The relevant parts of my Makefile looks like:
VPATH=altsrc:src:obj
$(A_OUT): $(OBS)
$(FORTRAN) -o $(A_OUT) $(OBS) $(LFLAGS)
obs/%.o: %.f
$(FORTRAN) $(FFLAGS) $< -o $#
This Makefile actually compiles the code OK, but it has one really obnoxious side effect: It finds each source file (and there are alot) and copies them out of altsrc or src into the directory where I am running make. This is really annoying and leads to a bunch of confusion later on. I haven't found any documentation anywhere that says this should be an effect of the VPATH macro. Can anyone tell me how to solve this? Thanks.
The trouble is that Make is RCS-savvy, and will check to see if a source file (e.g. td.f) can and should be updated from RCS. Yes, Make knows how to use co. If the source file isn't in such an archive (such as the source files in altsrc), then Make shrugs and gets on with the work.
The quickest, dirtiest solution is to use make -r. This will disable the built-in rules, which should solve the problem nicely... unless you rely on the built-in rules elsewhere.
If that won't do, you can override that particular rule with a do-nothing rule of your own, or with a rule that actually updates the sources in place, or you can touch the sources so that Make won't consider them out of date, or put the RCS files someplace where Make can't see them, or maybe two or three other options.

How to write rule to build object file when C files have different paths

I have bunch of C files, each with differnt path, so I have something like
SRC=/path1/path2/file1.c file2.c /usr/joe/files/file3.c
I want to build object file from each C file in build directory, so I did:
SRCBASE=$(notdir $(SRC))
OBJS= $(addprefix $(OBJDIR)/,$(SRCBASE:.c=.o))
This works fine, and I got the OBJS is build/file1.o build/file2.o build/file3.o
My question is how to write the implicit rule to build the object file, I tried to do:
build/%.o : %.c
gcc ....
But that seems now to work, since this rule did not catch the files with the full path.
I've tried to look at the gnu make, but did not find the answer there.
Many thanks.
You can use VPATH to locate files in other directories. Note that this does implicit searches, though, rather than using explicit paths. That is, you specify that you need file1.o through file3.o and that make should look first in ., then in /path1/path2, then in /usr/joe/files; so if . contains a file3.c you will get that one rather than the one in /usr/joe/files (or if not, but if there is one in /path1/path2, you will get that one).
It turns out that path searching is more often useful than explicit location anyway, so usually that's what you want. If you need to override something you just copy or symlink the "desired version" to the first place to be searched.

(Auto)make dependency across multiple makefiles

I am wondering if this is possible at all. Here is the situation:
My project uses automake to build its targets. The top-directory contains the usual configure.ac and Makefile.am. Amongst others, the Makefile.am contains a SUBDIRS variable listing the subdirectories, important for my question is the doc and include directory. The include directory's makefile looks like:
nobase_include_HEADERS = <lot-of-headers>
so it basically installs the headers. The makefile in doc is supposed to generate html documentation out of those files:
doxygen-stamp: Doxyfile
$(DOXYGEN) $<
echo "timestamp for Doxyfile" > $#
all-local: doxygen-stamp
Everything works fine so far, but if I change any of the headers in include the documentation is still up-to-date - because I did not list them as dependencies. What I would like to have is to have a doxygen-stamp-target that is rebuilt once the headers change without again listing all headers as dependencies. Is that possible and if it is, how?
In this case, using a single Makefile would be hinted at — though you can split it up by using the automake include instruction (also see section 7.3 "An alternative approach to subdirectories" of the am manual). Therefore:
#can't use nobase_
include_HEADERS = include/foo.h include/bar.h
doc/doxygen-stamp: ${include_HEADERS}
I think if you make doxygen-stamp also depend on '$(top_srcdir)/include/*.h' (or .hpp or whatever) it will rebuild when doxygen-stamp is out of date relative to any .h file in the include directory.
doxygen-stamp: Doxyfile $(top_srcdir)/include/*.h

Resources