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
Related
I have a large mostly Python project that I am trying to document. Part of this project is dependent on C++ source code which is made accessible via Cython.
When running the code like normal it runs fine, but in trying to do auto documenting with Sphinx I have run into issues. I think this guy had the right idea, but I cant make it work.
My Makefile looks like this
# Minimal makefile for Sphinx documentation
#
# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
SOURCEDIR = .
BUILDDIR = _build
# Put it first so that "make" without argument is like "make help".
help:
#$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help Makefile
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
#$(SPHINXBUILD) -M $# "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
How can I tell Sphinx to run python setup.py build_ext --inplace and then reference the output .so file(s) before analyzing the code?
Thank you for your time.
You would want to add the step from the answer you linked as part of the Makefile generated from sphinx to before any sphinx specific command was executed.
# Minimal makefile for Sphinx documentation
#
# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
SOURCEDIR = .
BUILDDIR = _build
# Put it first so that "make" without argument is like "make help".
help:
#$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help Makefile
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
#cd /path/to/setup.py; python setup.py build_ext --inplace
#$(SPHINXBUILD) -M $# "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
Adding it above the catch-all command that sphinx generates means that the build command to generate cython code would be executed prior to the the sphinx related command.
I would suggest instead to structure the project directory to be more standard to what is used in python. Instead of having documentation be in the same directory as the source code instead have a separate directory for source code and documentation.
root directory/
myproject/ (source code for Cython module)
libs/ (generated .so files from Cython)
tests/ (directory to hold test cases that should run after building)
__init__.py
docs/
Makefile (from sphinx)
Makefile (project)
setup.py
The Makefile for the project would be responsible for building the source code and then building the documentation. Its Makefile would look similar to below:
.all:
#python setup.py build_ext
#cd tests; $(MAKE) python -m unittest
#cd docs; $(MAKE) html
The first part of all would generate the source code (and should be updated to place the .so files generated to the libs/ folder). The second part would go into the tests/ directory and run unittests (example with python's unittest library). The third part would go into the docs/ directory and run make for the target html using the Makefile generated by Sphinx. To do this you would also want to update the tests and docs to include libs/ in their path so that way they can import the .so files generated from the build. (Note: # symbol prevents the line from being output to the console. This should be omitted if it is desired to be seen as part of a build)
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.
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
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.