| # common.mk: A common makefile helper for building daemons in Chromium OS |
| |
| ## Overview |
| |
| `common.mk` is a centralized Makefile providing a large number of features that |
| ease regular development: |
| |
| - known good linker and compiler flags |
| - target helpers for statically and dynamically linked binaries |
| - target helpers for statically and dynamically linked libraries |
| - target helper for running unittests under valgrind and qemu (when needed) |
| - separation of build artifacts and source code |
| |
| In addition, `common.mk` systems are fully parallelizable for all targets |
| avoiding truncated file issues while still utilizing bigsmp systems as |
| completely as possible. |
| |
| ## Usage |
| |
| A new project should create a top-level Makefile and after the boilerplate, |
| include `common.mk`. After doing so, they may define their targets as usual. |
| If there are subdirectories, they will be pulled in automatically if they |
| contain a `module.mk` file. This file will be just like the top-level Makefile |
| except that all targets and dependencies should be referred to by their |
| relative path to the top-level src. E.g., `lib/foo.o` instead of just `foo.o`. |
| |
| The Makefile may be called from the source directory with just `make` or from |
| any other location with `make -C /path/to/source`. If the build artifacts |
| should live somewhere other than `$PWD/build-$MODE`, then it may be called with |
| `make -C /path/to/source OUT=$PWD`, for instance. In addition to `OUT` and |
| `MODE`, there are several commandline variables which may be set. See the |
| comment in `common.mk` for full explanation and defaults. |
| |
| [`example/`](example/) contains a fully working example of a make hierarchy |
| that explores all the different ways `common.mk` can be used. |
| |
| ## Recipes |
| |
| This section is a brief recipe book to some common activities, but you should |
| consult the `common.mk` file for detailed information. In these recipes replace |
| `<text>` with the appropriate text for your situation. These recipes assume |
| that you have organized your Makefile along the lines of the other recipes, |
| i.e. the add flag recipe assumes your targets follow the add target recipes. |
| |
| For libraries these recipes assume that you want to build the PIE versions of |
| libraries. You have the option of building PIC versions by replacing where |
| `.pie.` is used with `.pic.`. One of these must be present, since `common.mk` |
| is looking to parse these out and there isn't a default behaviour. |
| |
| ### Adding a flag to a target: |
| |
| - Add flag to `<target>_FLAGS =` line or add a line `<target>_FLAGS += flag`. |
| |
| ### Adding a library to a target: |
| |
| - Add `-l<library>` to `<target>_LIBS =` line or add a line |
| `<target>_LIBS += -l<library>`. |
| |
| ### Adding a complex dependency, like gtk, when `<target>_DEPS` exists: |
| |
| - Add proper `pkg_config` name of the dependency to the `<target>_DEPS =` line. |
| |
| ### Adding a complex dependency, like gtk, when `<target>_DEPS` does not exist: |
| |
| - Add a `<target>_DEPS =` line before the related `FLAGS` and `LIBS` lines, |
| with the proper `pkg_config` name of your dependency. |
| - Change `<target>_FLAGS =` to `<target>_FLAGS :=` and add |
| `$(shell $(PKG_CONFIG) --cflags $(<target>_DEPS))` to the line. |
| - Change `<target>_LIBS =` to `<target>_LIBS :=` and add |
| `$(shell $(PKG_CONFIG) --libs $(<target>_DEPS))` to the line. |
| |
| ### Add a new source file, with name `<filename>.cc` to a existing target: |
| - Add `<filename>.o` to `<target>_OBJS`. |
| - Follow the instructions above for adding a new flags, libs and deps |
| related to the file. |
| |
| ### Add a new library target dependency to binary target: |
| - Add `CXX_STATIC_LIBRARY(lib<library>.pie.a)` to the dependencies of |
| `CXX_BINARY(<binary>)`. |
| |
| ### Add a new binary target: |
| - When creating the DEPS, FLAGS, and LIBS lines try to reuse existing |
| definitions that make sense instead of declaring everything anew. |
| - If needed, add `<target>_DEPS =` line with dependency list |
| - Add `<target>_FLAGS =` line with flags list. |
| - Add `<target>_LIBS =` line with library list. |
| - Add `<target>_OBJS =` line with object list. The object list is composed of |
| the `.cc` source files that are needed for the target, with `.o` replacing |
| the `.cc`. |
| - Add `CXX_BINARY(<target>): $(<target>_OBJS) ...` line. This line should have |
| any library dependencies that are built in this file included on it. How to |
| do this is discussed above. |
| - Add remaining boilerplate: |
| ``` |
| CXX_BINARY(<target>): CPPFLAGS += $(<target>_FLAGS) |
| CXX_BINARY(<target>): LDLIBS += $(<target>_LIBS) |
| clean: CLEAN(<target>) |
| all: CXX_BINARY(<target>) |
| ``` |
| |
| ### Add a new unit test target: |
| It is assumed there is a <parent> binary or library target that defines the |
| environment. |
| - Add `<target>_FLAGS =` line with `$(<parent>_FLAGS)` and any other needed |
| flags. |
| - Add `<target>_LIBS =` line with `$(<parent>_LIBS) -lgtest -lgmock` and other |
| needed libs. |
| - Add `<target>_OBJS> =` line with the objects for the unit tests` |
| - Add `CXX_BINARY(<target>): $(<target>_OBJS) ...` line. This line should have |
| any library dependencies that are built in this file included on it. How to |
| do this is discussed above. |
| - Add remaining boilerplate: |
| ``` |
| CXX_BINARY(<target>): CPPFLAGS += $(<target>_FLAGS) |
| CXX_BINARY(<target>): LDLIBS += $(<target>_LIBS) |
| clean: CLEAN(<target>) |
| tests: TEST(CXX_BINARY(<target>)) |
| ``` |
| |
| ### Add a new library target: |
| - When creating the DEPS, FLAGS, and LIBS lines try to reuse existing |
| definitions that make sense instead of declaring everything anew. |
| If needed, add `<target>_DEPS =` line with dependency list |
| - Add `<target>_FLAGS =` line with flags list. |
| - Add `<target>_LIBS =` line with library list. |
| - Add `<target>_OBJS =` line with object list. The object list is composed of |
| the `.cc` source files that are needed for the target, with `.o` replacing |
| the `.cc`. |
| - Add `CXX_STATIC_LIBRARY(lib<target>.pie.a): $(<target>_OBJS) ...` line. |
| - Add remaining boilerplate: |
| ``` |
| CXX_STATIC_LIBRARY(<target>): CPPFLAGS += $(<target>_FLAGS) |
| CXX_STATIC_LIBRARY(<target>): LDLIBS += $(<target>_LIBS) |
| clean: CLEAN(<target>) |
| ``` |
| - Add a protocol buffer when there are already protocol buffers used from the |
| same package/location as yours: |
| - Add `<protobuf>.pb.cc` to `<package>_PROTO_BINDINGS =` line or add a line |
| `<package>_PROTO_BINDINGS += <protobuf>.pb.cc`. |
| - For every .o that depends on <protobuf>.pb.cc existing: |
| ``` |
| <target>.o.depends: <protobuf>.pb.cc |
| ``` |
| - For every .o that depends on <protobuf>.pb.h existing: |
| ``` |
| <target>.o.depends: <protobuf>.pb.h |
| ``` |
| |
| ### Add a protobuffer that is in a new package: |
| - Use the following template |
| ``` |
| <package>_PROTO_BINDINGS = |
| <package>_PROTO_PATH = $(SYSROOT)/<installed location of .proto files> |
| <package>_PROTO_HEADERS = $(patsubst %.cc,%.h,$(<package>_PROTO_BINDINGS)) |
| <package>_PROTO_OBJS = $(patsubst %.cc,%.o,$(<package>_PROTO_BINDINGS)) |
| $(<package>_PROTO_HEADERS): %.h: %.cc ; |
| $(<package>_PROTO_BINDINGS): %.pb.cc: $(<package>_PROTO_PATH)/%.proto |
| $(PROTOC) --proto_path=$(<package>_PROTO_PATH) --cpp_out=. $< |
| clean: CLEAN($(<package>_PROTO_BINDINGS)) |
| clean: CLEAN($(<package>_PROTO_HEADERS)) |
| clean: CLEAN($(<package>_PROTO_OBJS)) |
| # Add rules for compiling generated protobuffer code, as the CXX_OBJECTS list |
| # is built before these source files exists and, as such, does not contain |
| # them. |
| $(eval $(call add_object_rules,$(<package>_PROTO_OBJS),CXX,cc)) |
| ``` |
| - Use the above recipe to add in your protobufs |
| |
| ### NOTE: |
| If you have added in protocol buffer definitions directly to the package you |
| are working in, go undo that and figure out where they should actually go. If |
| you are really sure they should be in your package you are a bit on your own, |
| please feel free to contact chromium-os-dev@chromium.org. |