Given this Makefile snippet:
TARGETS = ${SHARED_LIB_A} ${SHARED_LIB_B}
.PHONY: subdirs $(SUBDIRS)
subdirs: $(SUBDIRS)
$(SUBDIRS):
$(MAKE) -C $#
all: $(TARGETS)
I want to modify this Makefile so that TARGETS get built after the PHONY target is run. Ie. TARGETS depends on the code in SUBDIRS being built - TARGETS needs to be run after SUBDIRS. Right now the way this works is that the PHONY target gets run (the subdirs are built), but not the all target (unless I specifically run it like 'make all' - but I want to avoid doing that if possible, I just want to run 'make' and have it build the subdirectories and then build TARGETS.
First, you should have all as the first rule, not the last one. Unless you specify a specific target on the make command line, it will run the first target in the makefile (here, subdirs).
Second, you should declare subdirs as a prerequisite of $(TARGETS); that will ensure that they are not built until after subdirs is complete:
all: $(TARGETS)
$(TARGETS): subdirs
Now, because subdirs is PHONY it means that $(TARGETS) will always be considered out of date and always be built, even if invoking subdirs didn't change any files. However, there's no other alternative as you've written your makefile here, because make cannot know what files (created by the submakes) you want to use to see if the library is out of date.
Alternatively you can specify that subdirs is an order-only prerequisite:
$(TARGETS): | subdirs
Related
I have several projects in a directory and I want to write a Makefile to build any subset or all of these projects. Each project is in a folder named after itself, which contains a Makefile.
How do I execute these Makefiles?
Here is what I tried:
# Define the project names
PROJECT_NAMES := \
Project_1 \
Project_2 \
Project_3
# Define default behaviour
default: all
# Rule to build all projects
all:
$(foreach project, $(PROJECT_NAMES), $(CURRENT_PROJECT))
# Rule to build single project
.PHONY $(CURRENT_PROJECT)
$(CURRENT_PROJECT):
$(MAKE) -C $(CURRENT_PROJECT) make
I think this question might have gone for something similar, but it was not answered:
How to make a Makefile call another Makefile rules?
Instead of passing arguments, prerequisites/dependencies should be used. Here is how I solved it:
# Define the project names
PROJECT_NAMES := \
Project_1 \
Project_2 \
Project_3
# Define default behaviour
default: all
# Rule to build all projects now depends on building individual projects
all: $(foreach project, $(PROJECT_NAMES), $(project)_build)
# Rule to build a single project
.PHONY: Project_%
Project_%:
#echo "****** Building $(subst _build,,$#) ******"
#$(MAKE) -C $(subst _build,,$#) all
When called without parameters, all projects are built. Any combination of individual projects can be built by simply passing the project names to the makefile such as:
make Project_1 Project_3
I'm wanting to use this library in my cmake project, however it comes with a configure file instead of CMakeLists.txt
#! /bin/sh
# waf configure wrapper
# based on http://code.google.com/p/waf/source/browse/configure
CUR_DIR=$PWD
#possible relative path
WORKINGDIR=`dirname $0`
cd $WORKINGDIR
#abs path
WORKINGDIR=`pwd`
cd $CUR_DIR
WAF=$WORKINGDIR/tools/waf
# Generates a Makefile. Requires that $WAF is set.
#
generateMakefile()
{
cat > Makefile << EOF
#!/usr/bin/make -f
# Waf Makefile wrapper
WAF_HOME=$CUR_DIR
all:
#$WAF build
all-debug:
#$WAF -v build
all-progress:
#$WAF -p build
install:
$WAF install --yes;
uninstall:
$WAF uninstall
clean:
#$WAF clean
distclean:
#$WAF distclean
#-rm -rf build
#-rm -f Makefile
check:
#$WAF check
dist:
#$WAF dist
.PHONY: clean dist distclean check uninstall install all
EOF
}
generateMakefile
"${WAF}" configure $*
exit $?
Are there automated tools for the conversion? Does CMake supoprt the use of configure files? Is there a rule of thumb for conversion - i.e. replace ... with add_library?
You don't need to convert an upstream library to cmake to be able to use it in cmake projects. As long as you're able to install and/or link to that library, you can configure your cmake project to use it.
A common pattern to consume third-party libraries with cmake is to use cmake's find_package() function by supplying your own special-purpose cmake module files to find and configure the library.
Say, you're hoping to load libfoo. Here are the steps:
create a directory within your project tree to store your custom cmake modules (say, ./cmake/modules)
in that directory create a text file named FindFoo.cmake.
Within FindFoo.cmake add checks to determine if foo is actually present in the system. If it is then set the relevant variables. Otherwise, throw an error. The ideal thing is to create a build target for that library, which you can simply add as dependencies to other cmake targets.
Configure your cmake project to use your local modules by adding set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/modules/"),
Finally, configure your cmake project to include your Foo library by calling find_package(Foo REQUIRED).
The way to do the conversion is to read the configure script and understand what it does and how/why. Then write a CMakeLists.txt file that achieves the same.
There are no shortcuts.
I am new to CDT and I am trying to generate the makefile automatically. I notice that it include three files that doesn't exist at all, makefile.init, makefile.defs, makefile.targets.
Just wondering, what do they do? and why are they there?
################################################################################
# Automatically-generated file. Do not edit!
################################################################################
-include ../makefile.init
RM := rm -rf
# All of the sources participating in the build are defined here
-include sources.mk
-include subdir.mk
-include objects.mk
#Other codes
-include ../makefile.defs
# Add inputs and outputs from these tool invocations to the build variables
#Other codes
-include ../makefile.targets
The three includes are intended for your sake.
If you need to compile something proprietary manually, or copy files or anything you can come up with before the main program is compiled, you create the file makefile.init in the source directory and put your makefile-stuff in here.
The same applies to the other files just at other times in the compile chain.
I'm working on a project with a few directories with my makefile one level above all of them. When I update and of the code/header files and re-make, it says 'Nothing to be done for 'all''. Is there a way to force make to check all of the directories and therefore realise that some components have to be remade? Cheers
Jack
You could forcibly enter the sub-directories each time:
SUBDIRS = dir1 dir2
.PHONY: all
all: subdirs final_target
.PHONY: subdirs
subdirs:
for d in $(SUBDIRS); do $(MAKE) -C $$d; done
.PHONY: final_target
final_target:
echo "Do something here..."
This scheme, to enter all sub-directories, are actually very common.
I have written a CMakeLists.txt file including 2 executables (target1 and target2):
ADD_EXECUTABLE(target1 ${CXX_FILES})
TARGET_LINK_LIBRARIES(target1 ${requiredlibs})
ADD_EXECUTABLE(target2 ${CXX_FILES} ${OTHER_CXX_FILES})
TARGET_LINK_LIBRARIES(target2 ${requiredlibs})
Now every time when I run make without any parameters both targets are rebuilt. But I want to define target1 as default executable so that running make without any parameters only builds target1. For building target2 I would run make target2.
Is this possible?
In the Makefile created by CMake there is the following definition:
default_target: all
I think I need a way to set this default_target to target1.
Another problem I have is that make always rebuilds the targets, even if no source file has been changed.
An example CMakeLists.txt that does what you requested:
ADD_EXECUTABLE(target1 a.c)
ADD_EXECUTABLE(target2 EXCLUDE_FROM_ALL b.c)
For me it does not rebuild the target if the source files are not changed (or modification time did not change). Output I get:
$ make -f Makefile
Scanning dependencies of target target1
[100%] Building C object CMakeFiles/target1.dir/a.c.o
Linking C executable target1
[100%] Built target target1
[$ make -f Makefile
[100%] Built target target1
Note that the second make does not rebuild anything.
(you could read the CMake manual for this type of information)