The project is about a root directory that contains a src directory. I created two makefiles, one at the top directory and the other at the src directory. Here is the makefile of the src directory:
## Process this file with automake to produce Makefile.in
## Created by Netbeans
AM_CPPFLAGS = \
-DPACKAGE_LOCALE_DIR=\""$(localedir)"\" \
-DPACKAGE_SRC_DIR=\""$(srcdir)"\" \
-DPACKAGE_DATA_DIR=\""$(pkgdatadir)"\"
bin_PROGRAMS = scratchautotool
program_INCLUDE_DIRS := /usr/bin/PR__bin
program_LIBRARY_DIRS := /usr/lib/PR__lib
CFLAGS += $(foreach includedir,$(program_INCLUDE_DIRS),-I$(includedir))
AM_LDFLAGS += $(foreach librarydir,$(program_LIBRARY_DIRS),-L$(librarydir))
scratchautotool_SOURCES = \
main.c \
Task.c \
SeedVP.c
depend :
makedepend --$(CFLAGS) --$(scratchautotool_SOURCES)
The makefile of the root directory is shown below:
## Process this file with automake to produce Makefile.in
## Created by Netbeans
SUBDIRS = src
scratchautotooldocdir = ${prefix}/doc/scratchautotool
scratchautotooldoc_DATA = \
README\
COPYING\
AUTHORS\
ChangeLog\
INSTALL\
NEWS
INTLTOOL_FILES = intltool-extract.in \
intltool-merge.in \
intltool-update.in
EXTRA_DIST = $(scratchautotooldoc_DATA) \
$(INTLTOOL_FILES)
DISTCLEANFILES = intltool-extract \
intltool-merge \
intltool-update \
po/.intltool-merge-cache
# Remove doc directory on uninstall
uninstall-local:
-rm -r $(scratchautotooldocdir)
but while I was invoking make from the terminal it gave me the following error:
Making all in src
make[2]: Entering directory `../src'
make[2]: *** No rule to make target `all'. Stop.
make[2]: Leaving directory `../src'
The error is pretty clear: it is expecting to find the target all, and isn't. I'm assuming you called make without specifying a target; the default is (surprise!) all.
I want to share the solution for my question with any one who will encounter the same issue, I have modified the makefile as shown below:
all: scratchautotool
depend :
makedepend $(CFLAGS) $(scratchautotool_SOURCES)
but this also gave the same error, so I've searched and I've found that the makedepend didn't exist so I had to install xutils-dev package(which includes the program makedepend) using the below command:
sudo apt-get install xutils-dev
but this command solves the above mentioned issue only! but the makefile now has a new issue :)
Related
I am trying to link with static C API version of the TensorFlow library.
I built the static library using the following commands:
// get the sources
git clone https://github.com/tensorflow/tensorflow.git tensorflow_src
// create a build directory
mkdir builddir
cd builddir
// build the lib using CMake
cmake -S ../tensorflow_src/tensorflow/lite/c -DTFLITE_C_BUILD_SHARED_LIBS:BOOL=OFF
cmake --build . -j
This builds the libtensorflow-lite.a. However, the libtensorflow-lite.a is not self-contained and has its own set of 10 dependencies, stated here in the CMake file:
# TensorFlow Lite dependencies.
find_package(absl REQUIRED)
find_package(eigen REQUIRED)
find_package(farmhash REQUIRED)
find_package(fft2d REQUIRED)
find_package(flatbuffers REQUIRED)
find_package(gemmlowp REQUIRED)
find_package(neon2sse REQUIRED)
find_package(clog REQUIRED)
find_package(cpuinfo REQUIRED) #CPUINFO is used by XNNPACK and RUY library
find_package(ruy REQUIRED)
The question is, how do I find out the .a names of the required sub-libraries?
I used find ./builddir -type f -name "*.a" to list the libraries built by CMake, and expected roughly 10 libs, but the actual list is too long:
./_deps/xnnpack-build/libXNNPACK.a
./_deps/ruy-build/ruy/libruy_pack_avx2_fma.a
./_deps/ruy-build/ruy/libruy_have_built_path_for_avx2_fma.a
./_deps/ruy-build/ruy/libruy_block_map.a
./_deps/ruy-build/ruy/libruy_system_aligned_alloc.a
./_deps/ruy-build/ruy/libruy_have_built_path_for_avx512.a
./_deps/ruy-build/ruy/profiler/libruy_profiler_instrumentation.a
./_deps/ruy-build/ruy/libruy_trmul.a
./_deps/ruy-build/ruy/libruy_cpuinfo.a
./_deps/ruy-build/ruy/libruy_blocking_counter.a
./_deps/ruy-build/ruy/libruy_pack_arm.a
./_deps/ruy-build/ruy/libruy_apply_multiplier.a
./_deps/ruy-build/ruy/libruy_kernel_avx2_fma.a
./_deps/ruy-build/ruy/libruy_prepacked_cache.a
./_deps/ruy-build/ruy/libruy_tune.a
./_deps/ruy-build/ruy/libruy_context_get_ctx.a
./_deps/ruy-build/ruy/libruy_have_built_path_for_avx.a
./_deps/ruy-build/ruy/libruy_ctx.a
./_deps/ruy-build/ruy/libruy_wait.a
./_deps/ruy-build/ruy/libruy_allocator.a
./_deps/ruy-build/ruy/libruy_context.a
./_deps/ruy-build/ruy/libruy_kernel_avx.a
./_deps/ruy-build/ruy/libruy_prepare_packed_matrices.a
./_deps/ruy-build/ruy/libruy_pack_avx512.a
./_deps/ruy-build/ruy/libruy_kernel_arm.a
./_deps/ruy-build/ruy/libruy_denormal.a
./_deps/ruy-build/ruy/libruy_kernel_avx512.a
./_deps/ruy-build/ruy/libruy_frontend.a
./_deps/ruy-build/ruy/libruy_pack_avx.a
./_deps/ruy-build/ruy/libruy_thread_pool.a
./_deps/flatbuffers-build/libflatbuffers.a
./_deps/fft2d-build/libfft2d_fftsg2d.a
./_deps/fft2d-build/libfft2d_fftsg.a
./_deps/farmhash-build/libfarmhash.a
./_deps/clog-build/libclog.a
./_deps/abseil-cpp-build/absl/synchronization/libabsl_graphcycles_internal.a
./_deps/abseil-cpp-build/absl/synchronization/libabsl_synchronization.a
./_deps/abseil-cpp-build/absl/strings/libabsl_strings.a
./_deps/abseil-cpp-build/absl/strings/libabsl_str_format_internal.a
./_deps/abseil-cpp-build/absl/strings/libabsl_cord.a
./_deps/abseil-cpp-build/absl/strings/libabsl_strings_internal.a
./_deps/abseil-cpp-build/absl/status/libabsl_status.a
./_deps/abseil-cpp-build/absl/hash/libabsl_city.a
./_deps/abseil-cpp-build/absl/hash/libabsl_wyhash.a
./_deps/abseil-cpp-build/absl/hash/libabsl_hash.a
./_deps/abseil-cpp-build/absl/flags/libabsl_flags_reflection.a
./_deps/abseil-cpp-build/absl/flags/libabsl_flags_program_name.a
./_deps/abseil-cpp-build/absl/flags/libabsl_flags_internal.a
./_deps/abseil-cpp-build/absl/flags/libabsl_flags_private_handle_accessor.a
./_deps/abseil-cpp-build/absl/flags/libabsl_flags_marshalling.a
./_deps/abseil-cpp-build/absl/flags/libabsl_flags_commandlineflag_internal.a
./_deps/abseil-cpp-build/absl/flags/libabsl_flags_commandlineflag.a
./_deps/abseil-cpp-build/absl/flags/libabsl_flags_config.a
./_deps/abseil-cpp-build/absl/flags/libabsl_flags.a
./_deps/abseil-cpp-build/absl/numeric/libabsl_int128.a
./_deps/abseil-cpp-build/absl/debugging/libabsl_symbolize.a
./_deps/abseil-cpp-build/absl/debugging/libabsl_debugging_internal.a
./_deps/abseil-cpp-build/absl/debugging/libabsl_demangle_internal.a
./_deps/abseil-cpp-build/absl/debugging/libabsl_stacktrace.a
./_deps/abseil-cpp-build/absl/base/libabsl_spinlock_wait.a
./_deps/abseil-cpp-build/absl/base/libabsl_raw_logging_internal.a
./_deps/abseil-cpp-build/absl/base/libabsl_malloc_internal.a
./_deps/abseil-cpp-build/absl/base/libabsl_throw_delegate.a
./_deps/abseil-cpp-build/absl/base/libabsl_exponential_biased.a
./_deps/abseil-cpp-build/absl/base/libabsl_base.a
./_deps/abseil-cpp-build/absl/base/libabsl_log_severity.a
./_deps/abseil-cpp-build/absl/time/libabsl_time_zone.a
./_deps/abseil-cpp-build/absl/time/libabsl_civil_time.a
./_deps/abseil-cpp-build/absl/time/libabsl_time.a
./_deps/abseil-cpp-build/absl/container/libabsl_hashtablez_sampler.a
./_deps/abseil-cpp-build/absl/container/libabsl_raw_hash_set.a
./_deps/abseil-cpp-build/absl/types/libabsl_bad_variant_access.a
./_deps/abseil-cpp-build/absl/types/libabsl_bad_optional_access.a
./_deps/cpuinfo-build/libcpuinfo.a
The state of the libs seems to be the following:
absl: 30 libraries found
eigen: OK, template library defined in the headers
farmhash: OK, 1 library found
fft2d: OK, 2 libraries found
flatbuffers: OK, 1 library found
gemmlowp: OK, headers only
neon2sse: OK, headers only
clog: OK, 1 library found
cpuinfo: OK, 1 library found
ruy: 30 libraries found
All in all, most libs are OK, either there is 1 lib to link with, or the libs are header-only. What remains to be the problem are:
absl
ruy
because they contain about 30 .a libs.
Not sure if I have to link with all of those? It would be very cumbersome, as my build system is Meson and I am using custom_target() to link with TensorFlow.
A year later, but I just went through this myself, so here goes my answer.
Based on my experience (using a makefile and without your -DTFLITE_C_BUILD_SHARED_LIBS:BOOL=OFF) a program that performs inference does not need to link to Abseil.
You need to link to all other libs you mentioned, except ruy_kernel_arm and ruy_pack_arm, assuming you're running your program on the x64 platform. (Annoyingly -DTFLITE_ENABLE_RUY=OFF is not respected when building TfLite, so you're stuck with Ruy)
Detailed steps:
Build TfLite:
mkdir ~/my_tflite_project
cd ~/my_tflite_project/
git clone https://github.com/tensorflow/tensorflow.git tensorflow_src
mkdir tflite_build_x64
cd tflite_build_x64/
cmake ../tensorflow_src/tensorflow/lite/
/* You may encounter two CMake messages:
-- The Fortran compiler identification is unknown
I believe a Fortran compiler is only necessary to build Fortran bindings for TfLite.
-- Could NOT find CLANG_FORMAT: Found unsuitable version "0.0", but required is exact version "9" (found CLANG_FORMAT_EXECUTABLE-NOTFOUND)
sudo apt install clang-format-9
Annoyingly you need clang-format-9, plain clang-format (version 13, the newest) won't do. */
cmake --build . -j 4
Relevant libs:
$ cd ~/my_tflite_project/tflite_build_x64
$ ls *.a
libtensorflow-lite.a
$ ls pthreadpool/*.a
pthreadpool/libpthreadpool.a
$ ls _deps/*/*.a
_deps/clog-build/libclog.a _deps/farmhash-build/libfarmhash.a _deps/fft2d-build/libfft2d_fftsg2d.a _deps/xnnpack-build/libXNNPACK.a
_deps/cpuinfo-build/libcpuinfo.a _deps/fft2d-build/libfft2d_fftsg.a _deps/flatbuffers-build/libflatbuffers.a
$ ls _deps/ruy-build/ruy/*.a
_deps/ruy-build/ruy/libruy_allocator.a _deps/ruy-build/ruy/libruy_ctx.a _deps/ruy-build/ruy/libruy_kernel_avx.a _deps/ruy-build/ruy/libruy_prepacked_cache.a
_deps/ruy-build/ruy/libruy_apply_multiplier.a _deps/ruy-build/ruy/libruy_denormal.a _deps/ruy-build/ruy/libruy_kernel_avx2_fma.a _deps/ruy-build/ruy/libruy_prepare_packed_matrices.a
_deps/ruy-build/ruy/libruy_block_map.a _deps/ruy-build/ruy/libruy_frontend.a _deps/ruy-build/ruy/libruy_kernel_avx512.a _deps/ruy-build/ruy/libruy_system_aligned_alloc.a
_deps/ruy-build/ruy/libruy_blocking_counter.a _deps/ruy-build/ruy/libruy_have_built_path_for_avx.a _deps/ruy-build/ruy/libruy_pack_arm.a _deps/ruy-build/ruy/libruy_thread_pool.a
_deps/ruy-build/ruy/libruy_context.a _deps/ruy-build/ruy/libruy_have_built_path_for_avx2_fma.a _deps/ruy-build/ruy/libruy_pack_avx.a _deps/ruy-build/ruy/libruy_trmul.a
_deps/ruy-build/ruy/libruy_context_get_ctx.a _deps/ruy-build/ruy/libruy_have_built_path_for_avx512.a _deps/ruy-build/ruy/libruy_pack_avx2_fma.a _deps/ruy-build/ruy/libruy_tune.a
_deps/ruy-build/ruy/libruy_cpuinfo.a _deps/ruy-build/ruy/libruy_kernel_arm.a _deps/ruy-build/ruy/libruy_pack_avx512.a _deps/ruy-build/ruy/libruy_wait.a
Construct MWE using TfLite:
$ cd ~/my_tflite_project
$ mkdir my_dev_x64
$ cd my_dev_x64/
/* Construct minimal.cpp and makefile below */
$ cat minimal.cpp
#include "tensorflow/lite/model.h"
#include "tensorflow/lite/interpreter.h"
#include "tensorflow/lite/kernels/register.h"
#include <iostream>
int main() {
std::unique_ptr<tflite::FlatBufferModel> model = tflite::FlatBufferModel::BuildFromFile("your_network_here.tflite");
tflite::ops::builtin::BuiltinOpResolver resolver;
std::cout "Done\n";
return EXIT_SUCCESS;
}
$ cat makefile
COMPILER := g++
LINKER := g++
CXX_FILES := minimal.cpp
OBJ_FILES := $(CXX_FILES:.cpp=.o)
EXE_FILE := app
INCLUDE_DIRS := -I../tensorflow_src -I../tflite_build_x64/flatbuffers/include
LIB_DIRS := \
-L../tflite_build_x64 \
-L../tflite_build_x64/_deps/fft2d-build \
-L../tflite_build_x64/_deps/flatbuffers-build \
-L../tflite_build_x64/_deps/ruy-build/ruy \
-L../tflite_build_x64/_deps/farmhash-build \
-L../tflite_build_x64/_deps/xnnpack-build \
-L../tflite_build_x64/_deps/cpuinfo-build \
-L../tflite_build_x64/_deps/clog-build \
-L../tflite_build_x64/pthreadpool
LIBS := \
-ltensorflow-lite \
-lfft2d_fftsg \
-lfft2d_fftsg2d \
-lflatbuffers \
-lruy_ctx \
-lruy_allocator \
-lruy_frontend \
-lruy_context_get_ctx \
-lruy_context \
-lruy_apply_multiplier \
-lruy_prepacked_cache \
-lruy_tune \
-lruy_cpuinfo \
-lruy_system_aligned_alloc \
-lruy_prepare_packed_matrices \
-lruy_trmul \
-lruy_block_map \
-lruy_denormal \
-lruy_thread_pool \
-lruy_blocking_counter \
-lruy_wait \
-lruy_kernel_avx \
-lruy_kernel_avx2_fma \
-lruy_kernel_avx512 \
-lruy_pack_avx \
-lruy_pack_avx2_fma \
-lruy_pack_avx512 \
-lruy_have_built_path_for_avx \
-lruy_have_built_path_for_avx2_fma \
-lruy_have_built_path_for_avx512 \
-lfarmhash \
-lXNNPACK \
-lpthreadpool \
-lcpuinfo \
-lclog
CXX_FLAGS := -Wall #-pedantic
LINK_FLAGS :=
#Do not print the output of the commands
.SILENT:
#Phony targets do not represent actual files, so files with the following names are ignored
.PHONY: clean depend
#Link object files to form an executable file
$(EXE_FILE): $(OBJ_FILES)
$(LINKER) $(LINK_FLAGS) $(OBJ_FILES) -o $(EXE_FILE) $(LIB_DIRS) $(LIBS)
#Compile cpp files to object files
%.o: %.cpp
$(COMPILER) $(CXX_FLAGS) $(INCLUDE_DIRS) -c $<
#Remove object files, executable, and possible linkinfo files
clean:
-rm -f $(OBJ_FILES) $(EXE_FILE)
#Generate dependency file
depend:
$(COMPILER) $(CXX_FLAGS) $(INCLUDE_DIRS) -MM $(CXX_FILES) > make.dep
#Include dependency file
-include make.dep
Build and run MWE:
$ cd ~/my_tflite_project/my_dev_x64
$ make
$ ./app
Done
Hopefully that helps you or some other poor fellow to get TfLite C++ working.
I am trying to understand how to write my own makefile for small project, so I have a few questions
my project consists of src directory that contains main.c, file1.c, file2.c, header1.h, and finally header2.h these files use some library from non standard library that I have created and non standard header file, the library directory is located in usr/lib/pr__lib and the header directory is located in usr/include/lib
so I should create two makefile.am one will be located in src directory and the other one will be in root directory of the project the makefile.am of the src directory is as shown below:
program_NAME := PRDSL
bin_PROGRAMS = PRDSL_AutoProject
program_INCLUDE_DIRS := /usr/bin/PR__bin
program_LIBRARY_DIRS := /usr/lib/PR__lib
CFLAGS += $(foreach includedir,$(program_INCLUDE_DIRS),-I$(includedir))
program_LIBRARIES := \
libprdependency \
libprdynarray_pic \
libprhistogram_pic \
libprlistofarrays \
libprlistofarrays_pic \
libprmalloc \
libvreo_wrapper_library
AM_LDFLAGS += $(foreach librarydir,$(program_LIBRARY_DIRS),-L$(librarydir))
AM_LDFLAGS += $(foreach library,$(program_LIBRARIES),-l$(library))
PRDSL_AutoProject_SOURCES = \
main.c \
file1.c \
file2.c
depend :
makedepend --$(CFLAGS) --$(PRDSL_AutoProject_SOURCES)
all: $(program_NAME)
2nd makefile.am at the root directory is as shown below:
SUBDIRS = src
PRDSL_AutoProjectdocdir = ${prefix}/doc/PRDSL_AutoProject
PRDSL_AutoProjectdoc_DATA = \
README\
COPYING\
AUTHORS\
ChangeLog\
INSTALL\
NEWS
INTLTOOL_FILES = intltool-extract.in \
intltool-merge.in \
intltool-update.in
EXTRA_DIST = $(PRDSL_AutoProjectdoc_DATA) \
$(INTLTOOL_FILES)
DISTCLEANFILES = intltool-extract \
intltool-merge \
intltool-update \
po/.intltool-merge-cache
# Remove doc directory on uninstall
uninstall-local:
-rm -r $(PRDSL_AutoProjectdocdir)
but I get the below errors and warnings while I was running automake command:
src/Makefile.am:20: error: 'program_LIBRARIES' is used but 'programdir' is undefined
src/Makefile.am:18: warning: 'CFLAGS' is a user variable, you should not override it;
src/Makefile.am:18: use 'AM_CFLAGS' instead
src/Makefile.am:43: error: AM_LDFLAGS must be set with '=' before using '+='
could any one review it and help me?
For src/Makefile.am:43: error: AM_LDFLAGS must be set with '=' before using '+=' see my answer to your previous question.
Yes, the following lines are telling you to use AM_CFLAGS instead of CFLAGS because, as the error indicates, CFLAGS is a user-specified value and you should leave it alone.
src/Makefile.am:18: warning: 'CFLAGS' is a user variable, you should not override it;
src/Makefile.am:18: use 'AM_CFLAGS' instead
I believe, though I am far from certain, that the reason you are getting src/Makefile.am:20: error: 'program_LIBRARIES' is used but 'programdir' is undefined is because you are using a variable program_LIBRARIES that the autotools believe is a variable they should be using but that you are not using in that way and are instead using in the loop which sets the value for AM_LDFLAGS. As such, and assuming I am correct, if you rename that to not follow the autotool variable naming scheme I believe that error will go away.
I am trying to install the SCIP optimisation suite version 3.1.0
http://scip.zib.de/download.php?fname=scipoptsuite-3.1.0.tgz
The software is compiled by typing the 'make' command in the scipoptsuite-3.1.0 directory. The package contains three constituent packages (SCIP, soplex and zimpl). There is a makefile for the general package (scipoptsuite) and also a makefile for the three constituent packages. I am having great difficulties when it comes to the compilation of zimpl.
The error occurs when attempting to compile using the code within the zimpl makefile. There is an attempt to generate a library and to store object files within that library.
I am now going to provide some of the relevant code to the problem.
Here are some key definitions:
AR = ar cr
ARFLAGS =
RANLIB = ranlib
LIBBASE = blkmem.o bound.o code.o conname.o define.o elem.o entry.o \
hash.o heap.o idxset.o inst.o iread.o list.o \
load.o local.o metaio.o mmlparse2.o mmlscan.o mono.o \
mshell.o prog.o random.o rdefpar.o source.o \
setempty.o setpseudo.o setlist.o setrange.o setprod.o \
setmulti.o set4.o stmt.o stkchk.o strstore2.o symbol.o \
term2.o tuple.o vinst.o zimpllib.o
LIBDIR = lib
LIBRARY = $(LIBDIR)/lib$(LIBNAME).a
LIBNAME = $(NAME)-$(VERSION).$(BASE)
OBJDIR = obj/O.$(OSTYPE).$(ARCH).$(COMP).$(LINK).$(OPT)
LIBOBJ = $(LIBBASE) gmpmisc.o numbgmp.o
LIBXXX = $(addprefix $(OBJDIR)/,$(LIBOBJ))
And here is the key segment of code which causes the error:
$(LIBRARY): $(OBJDIR) $(LIBDIR) $(LIBXXX)
#echo "-> generating library $#"
-rm -f $(LIBRARY)
$(AR) $# $(LIBXXX) $(ARFLAGS)
$(RANLIB) $#
Which generates the following error message:
** Building ZIMPL library "mypath/scipoptsuite-3.1.0/zimpl-3.3.2/lib/libzimpl.linux.arm.gnu.opt.a".
make[2]: Entering directory `mypath/scipoptsuite-3.1.0/zimpl-3.3.2'
-> generating library lib/libzimpl-3.3.2.linux.arm.gnu.opt.a
ar: crs: No such file or directory
make[2]: *** [lib/libzimpl-3.3.2.linux.arm.gnu.opt.a] Error 1
make[2]: Leaving directory `mypath/scipoptsuite-3.1.0/zimpl-3.3.2'
make[1]: *** [mypath/scipoptsuite-3.1.0/zimpl-3.3.2/lib/libzimpl.linux.arm.gnu.opt.a] Error 2
make[1]: Leaving directory `mypath/scipoptsuite-3.1.0'
make: *** [scipbinary] Error 2
I would particularly like to bring your attention to the following line within that segment of code:
ar: crs: No such file or directory
I am not really sure what the 'crs' aspect of that line is referring to, or even why any error is generated at all. Any help on this matter would be greatly appreciated. I am truly stumped at this point.
Change :
AR = ar cr
ARFLAGS =
To :
ARFLAGS += cs
And :
$(AR) $# $(LIBXXX) $(ARFLAGS)
To :
$(AR) $(ARFLAGS) $# $(LIBXXX)
ar is to be invoked like this (man ar(1)):
ar [--plugin name] [-X32_64] [-]p[mod [relpos] [count]] [--target bfdname] archive [member...]
So its flags can't be at the end of the command line if not marked as such, like -crs.
Also, make already define $(AR) and $(ARFLAGS) for you, there is no need for you to specify it again.
$ make -p | grep "^AR"
AR = ar
ARFLAGS = rv
So I've got the following folder structure
makefile
src/my_lib.c
src/myhead.h
and I'm trying to compile *my_lib.c* with the header myhead.h as a library. This is the makefile. I attempt to put the obj files in OBJFOLDER and the compiled library in the OUTPUTFOLDER
PLUGNAME=my_lib
SOURCEFOLDER=src
OUTPUTFOLDER=bin
OBJFOLDER=bin/obj
OBJS=$(PLUGNAME).o
DEPS=myhead.h
# Configuration finishes here
_OBJS = $(patsubst %,$(OBJFOLDER)/%,$(OBJS))
_DEPS = $(patsubst %,$(SOURCEFOLDER)/%,$(DEPS))
ifeq ($(OS),Windows_NT)
EXT = .dll
else
UNAME_S := $(shell uname -s)
ifeq ($(UNAME_S),Linux)
EXT = .so
endif
endif
all : $(OUTPUTFOLDER)/$(PLUGNAME)$(EXT)
$(OUTPUTFOLDER)/$(PLUGNAME)$(EXT) : $(_OBJS)
gcc -Wl,--add-stdcall-alias -shared -o $# $(_OBJS)
$(OBJFOLDER)/%.o: $(SOURCEFOLDER)/%.c $(_DEPS)
mkdir -p $(OUTPUTFOLDER)
mkdir -p $(OBJFOLDER)
gcc $(foreach d, $(INC), -I$d) -c $< -o $#
.PHONY: clean
clean :
rm -f $(OBJFOLDER)/*.o $(OUTPUTFOLDER)/$(PLUGNAME)$(EXT) $(SOURCEFOLDER)/TSDRPlugin.h
When I do make all it fails
make: *** No rule to make target `bin/obj/my_lib.o', needed by `bin/
my_lib.dll'. Stop.
I have no idea how this could be possible since I already have defined
$(OBJFOLDER)/%.o: $(SOURCEFOLDER)/%.c $(_DEPS)
Strangely if I change the above line in the makefile, to
bin/obj/my_lib.o: $(SOURCEFOLDER)/%.c $(_DEPS)
I now get
make: *** No rule to make target `src/%.c', needed by `bin/obj/my_lib.o'. Stop.
Your second error is because by removing the % in the target you've turned this into an explicit rule, not a pattern rule. So, the % in the prerequisite is not replaced.
Your first error means that for some reason make is deciding that your pattern rule doesn't match. This means, usually, that make can't find and doesn't know how to create one of the prerequisites. I recommend you run make with the -d flag and see why make decides your rule doesn't apply.
What version of GNU make are you using? Some very old versions would not match pattern rules if the directory that the target was to be placed into didn't exist already.
The problem was that header was missing... Stupid mistake on my side.
I overlooked it, because this was a snippet from a longer makefile that was supposed to copy over the header but it didn't which means that this line was outputting the error. Stupid me...
First of all, sorry if I end up making a too long post, but I think it would be missing information otherwise.
I'd like to include my repository version in each build.
There is a main makefile that masters some other ones in their respective subdirectories.
The subprojects are "automaked".
I am trying to pass a variable containing the svnversion to inner Makefiles like this:
# Main Makefile
SUBDIRS = sd1 sd2
REPO_VERSION = `svnversion`
export ECHO = #echo
export CPPFLAGS
all: versioned
$(ECHO) "Build of all projects in $(PWD) finished."
clean :
$(ECHO) "Cleaning up entire project tree..."
-for d in $(SUBDIRS); do ($(ECHO) "Cleaning up \"$$d\""; $(MAKE) -C $$d clean ); done
.PHONY: versioned unversioned $(SUBDIRS)
versioned: CPPFLAGS = -DREPO_VERSION=\"v$(REPO_VERSION)\"
versioned: subdirs
unversioned: subdirs
versioned unversioned:
$(ECHO) "Build $# finished."
subdirs: $(SUBDIRS)
$(SUBDIRS):
$(ECHO) "== Building $# =="
$(ECHO) " [ CPPFLAGS = \"$(CPPFLAGS)\" ]"
( cd $# && \
( [ -f Makefile ] || \
( aclocal && \
autoheader && \
automake --foreign --add-missing && \
autoconf && \
configure ) ) && \
$(MAKE) \
)
Each subdirectory has a Makefile.am and configure.ac like this:
Makefile.am:
# Makefile.am in "sd1" and "sd2"
bin_PROGRAMS = app
app_SOURCES = source.c
configure.ac:
AC_PREREQ(2.59)
AC_INIT([app], [1.00], [<suport#domain>])
AM_INIT_AUTOMAKE
AC_CONFIG_HEADER([config.h])
# Checks for programs.
AC_PROG_CC
AC_PROG_CPP
AC_PROG_INSTALL
AC_PROG_LN_S
AC_PROG_MAKE_SET
# Checks for header files.
AC_HEADER_STDC
# Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
AC_TYPE_SIZE_T
# Output configuration files.
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
I expected this to work, but autotools are embedding REPO_VERSION in the makefile when run, and changes in the main Makefile's REPO_VERSION are ignored in further builds.
A piece of an output looks like this:
== Building sd1 ==
[ CPPFLAGS = "-DREPO_VERSION="1050"" ]
( cd sd1 && \
( [ -f Makefile ] || \
( aclocal && \
autoheader && \
automake --foreign --add-missing && \
autoconf && \
configure ) ) && \
make \
)
make[1]: Entrando no diretório `./recursive/sd1'
make all-am
make[2]: Entrando no diretório `./recursive/sd1'
gcc -DHAVE_CONFIG_H -I. -DREPO_VERSION=\"1049M\" -g -O2 -MT source.o -MD -MP -MF .deps/source.Tpo -c -o source.o source.c
mv -f .deps/source.Tpo .deps/source.Po
gcc -g -O2 -o app source.o
make[2]: Saindo do diretório `./recursive/sd1'
make[1]: Saindo do diretório `./recursive/sd1'
The program outputs:
> ./sd1/appVersão = [1049M].
This clearly is not what I wanted.
Can anybody here please give a way to fix this?
Thanks.
In your top level make file add
export REPO_VERSION
and modify each Makefile.am to have
REPO_VERSION ?= unknown
AM_CPPFLAGS = -DREPO_VERSION="$(REPO_VERSION)"
The export directive makes it so that the value of REPO_VERSION is exported to recursive make invocations. The Makefile.am snippet sets a default value for REPO_VERSION if it is not given (e.g. make is run from the shell in the subdirectory) and AM_CPPFLAGS specifies the default value of CPPFLAGS for all targets in that Makefile. If you have a target specific _CPPFLAGS variable, you should either add $(AM_CPPFLAGS) to that or include the -DREPO_VERSION="$(REPO_VERSION)" in it. With a bit more effort you can add some stuff into the configure.ac files so that the default for REPO_VERSION can be set at configure time.
You are trying to pass CPPFLAGS via the environment, but I don't see where the invocation of configure is getting CPPFLAGS set in its environment. Try passing it at the command line:
$(SUBDIRS):
$(ECHO) "== Building $# =="
$(ECHO) " [ CPPFLAGS = \"$(CPPFLAGS)\" ]"
cd $# && autoreconf -i && ./configure CPPFLAGS=$(CPPFLAGS) && $(MAKE)
Also, you are only running configure once. After the Makefile exists, you do not rerun configure, so you never reset the value of CPPFLAGS in the subdirectory.
Setting the version at configure time is very inconvenient. Take a look here for some techinques that allow the version to be set at make time.