Append to beginning of list - makefile

I have a makefile that lists the source files: (shortened to relevant)
SRCFOLDER=src/
SOURCES= main.cpp
OBJECTS=$(SOURCES:.cpp=.o)
and I would like to concate the strings together, but for each one in SOURCES. As you can see above, I do it for OBJECTS, but I want to do it like this: (pseudocode)
foreach(src in SOURCES)
src = concate(SRCFOLDER, src)
so that if SOURCES was main.cpp window.cpp, the result would be src/main.cpp src/window.cpp.
I tried this:
SOURCES=$(SOURCES:*=$(SRCFOLDER)/*)
but I get this error:
makefile:12: *** Recursive variable `SOURCES' references itself (eventually). Stop.

SRCFOLDER := src
SOURCES := main.cpp window.cpp
SOURCES := $(addprefix $(SRCFOLDER)/, $(SOURCES))

Related

missing MODULE_LICENSE() when two module using same object file

I have two files:
main.c will become module calc, it will use API in expression.c.
livepatch-calc.c will become module livepatch-calc.
I have following makefile and work well
obj-m += calc.o
obj-m += livepatch-calc.o
calc-objs += main.o expression.o
ccflags-y := -std=gnu99 -Wno-declaration-after-statement
Currently, I need call expression's API in livepatch-calc.c. So, I have new makefile like:
obj-m += calc.o
obj-m += livepatch-calc.o
calc-objs += main.o expression.o
livepatch-calc-objs += expression.o
ccflags-y := -std=gnu99 -Wno-declaration-after-statement
Unfortunately, when I make it. Warning message show up:
WARNING: modpost: missing MODULE_LICENSE() in ..../livepatch-calc.o
I wondering are there anything wrong in my makefile?

CGO linking error: undefined reference to `MemoryFreeLibrary'

I am trying to wrap around a C library with Go. The library is built with CMake and produces a static library file. I added the #cgo stuff at the beginning of the .go file with the proper CFLAGS and LDFLAGS, however, I keep getting undefined reference errors when running go build memorymodule.go.
Here is my code:
package main
/*
#cgo CFLAGS: -IMemoryModule
#cgo LDFLAGS: MemoryModule/build/MemoryModule.a
#include "MemoryModule/MemoryModule.h"
*/
import "C"
import (
"fmt"
"io/ioutil"
"os"
"unsafe"
)
const SIZE int = 1024
func end(msg string) {
fmt.Println(msg)
os.Exit(1)
}
func check(err error, msg string) {
if err != nil {
end(msg)
}
}
func main() {
bin, err := ioutil.ReadFile(os.Args[0])
check(err, "error reading file")
// Convert the args passed to this program into a C array of C strings
var cArgs []*C.char
for _, goString := range os.Args {
cArgs = append(cArgs, C.CString(goString))
}
// Load the reconstructed binary from memory
handle := C.MemoryLoadLibraryEx(
unsafe.Pointer(&bin[0]), // void *data
(C.size_t)(len(bin)), // size_t
(*[0]byte)(C.MemoryDefaultAlloc), // Alloc func ptr
(*[0]byte)(C.MemoryDefaultFree), // Free func ptr
(*[0]byte)(C.MemoryDefaultLoadLibrary), // loadLibrary func ptr
(*[0]byte)(C.MemoryDefaultGetProcAddress), // getProcAddress func ptr
(*[0]byte)(C.MemoryDefaultFreeLibrary), // freeLibrary func ptr
unsafe.Pointer(&cArgs[0]), // void *userdata
)
// Execute binary
C.MemoryCallEntryPoint(handle)
// Cleanup
C.MemoryFreeLibrary(handle)
}
Here is the results from the go build ... with -x to help with debugging:
cd /home/wlaw/go-memory-module
i686-w64-mingw32-gcc -I . -m32 -mthreads -fmessage-length=0 -fdebug-prefix-map=$WORK=/tmp/go-build -gno-record-gcc-switches -o $WORK/command-line-arguments/_obj/_cgo_.o $WORK/command-line-arguments/_obj/_cgo_main.o $WORK/command-line-arguments/_obj/_cgo_export.o $WORK/command-line-arguments/_obj/memorymodule.cgo2.o -g -O2 MemoryModule/build/MemoryModule.a
# command-line-arguments
/tmp/go-build590803163/command-line-arguments/_obj/_cgo_main.o:_cgo_main.c:(.data+0x0): undefined reference to `MemoryDefaultLoadLibrary'
/tmp/go-build590803163/command-line-arguments/_obj/_cgo_main.o:_cgo_main.c:(.data+0x4): undefined reference to `MemoryDefaultGetProcAddress'
/tmp/go-build590803163/command-line-arguments/_obj/_cgo_main.o:_cgo_main.c:(.data+0x8): undefined reference to `MemoryDefaultFreeLibrary'
/tmp/go-build590803163/command-line-arguments/_obj/_cgo_main.o:_cgo_main.c:(.data+0xc): undefined reference to `MemoryDefaultFree'
/tmp/go-build590803163/command-line-arguments/_obj/_cgo_main.o:_cgo_main.c:(.data+0x10): undefined reference to `MemoryDefaultAlloc'
/tmp/go-build590803163/command-line-arguments/_obj/memorymodule.cgo2.o: In function `cgo_50ced23471ff_Cfunc_MemoryCallEntryPoint':
/tmp/go-build/command-line-arguments/_obj/cgo-gcc-prolog:40: undefined reference to `MemoryCallEntryPoint'
/tmp/go-build590803163/command-line-arguments/_obj/memorymodule.cgo2.o: In function `cgo_50ced23471ff_Cfunc_MemoryLoadLibraryEx':
/tmp/go-build/command-line-arguments/_obj/cgo-gcc-prolog:76: undefined reference to `MemoryLoadLibraryEx'
/tmp/go-build590803163/command-line-arguments/_obj/memorymodule.cgo2.o: In function `cgo_50ced23471ff_Cfunc_MemoryFreeLibrary':
/tmp/go-build/command-line-arguments/_obj/cgo-gcc-prolog:54: undefined reference to `MemoryFreeLibrary'
collect2: error: ld returned 1 exit status
Makefile:9: recipe for target 'all' failed
make: *** [all] Error 2
Whats interesting is if I compile the MemoryModule dependency using make instead of CMake (by editing my Makefile) such that it produces an object file instead of a static library file, and modify my source code to link with that instead, I get no problems:
package main
/*
#cgo CFLAGS: -IMemoryModule
#cgo LDFLAGS: MemoryModule/MemoryModule.o
#include "MemoryModule/MemoryModule.h"
*/
import "C"
...
My Makefile for reference:
ifneq ("$(shell which i686-w64-mingw32-gcc)","")
compiler = i686-w64-mingw32-gcc
else
compiler = i586-mingw32msvc-gcc
endif
# Build the dependencies first (subdirs), then move onto the meat and potatoes.
all: MemoryModule
CC=$(compiler) CGO_ENABLED=1 GOOS=windows GOARCH=386 go build -x memorymodule.go
# Dependency build.
SUBDIRS = MemoryModule
subdirs: $(SUBDIRS)
$(SUBDIRS):
$(MAKE) -C $#
# Override default subdir build behavior (make) with cmake.
MemoryModule:
[ "`ls -A MemoryModule`" ] || git submodule update --init
# $(MAKE) -C $#
cmake -HMemoryModule -BMemoryModule/build
cmake --build MemoryModule/build --target MemoryModule
# Clean targed.
CLEANDIRS = $(SUBDIRS:%=clean-%)
clean: $(CLEANDIRS)
rm -f memorymodule.exe
$(CLEANDIRS):
$(MAKE) -C $(#:clean-%=%) clean
test:
$(MAKE) -C tests test
.PHONY: subdirs $(INSTALLDIRS) $(SUBDIRS) clean test
Any help would be appreciated!
Git project here: https://github.com/wheelerlaw/go-memory-module
Update:
Okay, so I stumbled across this SO question. So if I change my go build command to:
GOOS="windows" GOARCH="amd64" CGO_ENABLED="1" CC="x86_64-w64-mingw32-gcc" go build -x
from:
GOOS="windows" GOARCH="386" CGO_ENABLED="1" CC="i686-w64-mingw32-gcc" go build -x
... it works. So it looks like an incompatibility between the different archs. I'm going to download a 32 bit version of Go to see if that helps.
But what I don't understand is that the program compiles just fine even with the mis-matched archs when I compile C library into an object instead of a static library. Any ideas?

Makefile CFLAGS and SRCS-y are ignored in function form

I have some trouble with making Makefile. This is a part of Makefile.
dirs := fwd common bp bp_manager $(XRTE_HASH)
VPATH_ = $(foreach dir,$(dirs),$(SRCDIR)/$(dir))
INC_ = $(foreach dir,$(dirs),$(wildcard $(dir)/*.h))
CFLAGS_ = $(foreach dir,$(dirs),-I$(SRCDIR)/$(dir))
SRCS-y_ = $(foreach dir,$(dirs),$(notdir $(wildcard $(dir)/*.c)))
VPATH += $(VPATH_)
INC += $(INC_)
CFLAGS += $(CFLAGS_)
SRCS-y += $(SRCS-y_)
check:
echo $(CFLAGS)
echo $(SRCS-y)
VPATH and INC worked as I intended.
CFLAGS doesn't contain CFLAGS_
SRCS-y was printed as I inteded, but it has no effect when do "make" - SRCS-y_ was same with null.
CFLAGS and SRCS-y is okay when set manually (without function).
I thought Makefile is almost same with csh.
Can you explain me why the "make" ignores functions?
Thanks.
CFLAGS_ is just a string. $(CFLAGS_) is a variable's value. So you should have:
CFLAGS += $(CFLAGS_)
SRCS-y += $(SRCS-y_)

make: define multiple variables with pattern specific variable values

How do you define multiple variables using make's pattern specific variable values feature https://www.gnu.org/software/make/manual/html_node/Pattern_002dspecific.html#Pattern_002dspecific? For example, suppose that LIBDIR and RPATH have already been defined, and I want to set the following:
LDFLAGS += -L$(LIBDIR) $(RPATH)
LDLIBS += -lsomelibrary
for builds that match the pattern utest%. So for example,
utest% : -L$(LIBDIR) $(RPATH)
would get me halfway there, but then how to define the second variable?
I thought that maybe using multi-line variables https://www.gnu.org/software/make/manual/html_node/Multi_002dLine.html would work, but I can't quite get there. I've tried:
define linking_vars :=
LDFLAGS := -L$(LIBDIR) $(RPATH)
LDLIBS := -lsomelibrary
endef
utest% : $(linking_vars)
and also
define newline =
endef
utest_% : LDFLAGS := -L$(LIBDIR) $(RPATH) $(newline) LDLIBS := -lsomelibrary
but I haven't had any luck yet.
I'm not entirely sure I understand what you want to do, but it sounds as if this might do it:
utest% : LDFLAGS += -L$(LIBDIR) $(RPATH)
utest% : LDLIBS += -lsomelibrary

Jam Object rule and directories

I suspect that the manual is actually saying what I'm doing wrong, but I can't really see a solution; the problem occurs when the .c file and the .o file to be build are not in the same directory, and the .c file has an automatic dependency on a .h file which has to be generated on the fly. The problem can be probably be solved by manually setting dependencies between the .c and .h file, but I would like to avoid that.
I have the following directory structure:
weird/
Jamfile
b.c
src/
a.c
c.c
The src/a.c file is like this:
#include "src/a.h"
int main(int argc, char *argv[])
{
return 0;
}
The b.c file is like this:
#include "src/b.h"
int main(int argc, char *argv[])
{
return 0;
}
The src/c.c file is like this:
#include "c.h"
int main(int argc, char *argv[])
{
return 0;
}
The Jamfile is:
rule CreateHeader
{
Clean clean : $(1) ;
}
actions CreateHeader
{
echo "int x = 10;" > $(1)
}
Object a.o : src/a.c ;
Object b.o : b.c ;
Object c.o : src/c.c ;
CreateHeader src/a.h ;
CreateHeader src/b.h ;
CreateHeader src/c.h ;
The following command correctly creates b.o and src/b.h:
jam b.o
The following command creates src/a.h, but then GCC fails to create a.o; the reason is quite obviously that the #include in a.c mentions src/a.h while in fact should simply refer to a.h:
jam a.o
The following command fails completely, and does not even create c.h; the reason is probably that when Jam analyzes c.c it generates a dependency on c.h instead of src/c.h, and in the Jamfile there are no rules for generating c.h:
jam c.o
This command compiles properly if I explicitly ask to generate src/c.h before asking for c.o:
jam src/c.h
jam c.o
In my opinion the jam src/c.h should not be necessary. What's wrong here? Check the Jam manual for more information, particularly under the section Header File Scanning.
Added after I accepted the answer
I kept experimenting a little bit with the constructs suggested by the author of the accepted answer, and I'll post here the results. In this setting you can type:
jam app
And the application will be linked under bin/app. Unfortunately I had to use a UNIX path when setting LOCATE_TARGET, and my understanding is that this is not exactly a good practice.
Directory Structure:
project/
Jamfile
src/
main.c
gen/
bin/
obj/
File Jamfile:
SubDir TOP ;
rule CreateHeader
{
MakeLocate $(1) : $(LOCATE_SOURCE) ;
Clean clean : $(1) ;
}
actions CreateHeader
{
BUILD_DATE=`date`
echo "char build_date[] = \"$BUILD_DATE\";" > $(1)
}
SEARCH_SOURCE = src ;
LOCATE_TARGET = bin/obj ;
SubDirHdrs gen ;
Object main.o : main.c ;
LOCATE_TARGET = bin ;
MainFromObjects app : main.o ;
LOCATE_SOURCE = gen ;
CreateHeader info.h ;
File src/main.c
src/main.c
#include <stdio.h>
#include "info.h"
int main(int argc, char *argv[])
{
printf("Program built with Jam on %s.\n", build_date);
return 0;
}
Changing all #include directives to omit the path (i.e. '#include "a.h' etc.) and changing the Jamfile to the following will solve your issues:
SubDir TOP ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) src ] ;
LOCATE_SOURCE = [ FDirName $(SUBDIR) src ] ;
rule CreateHeader
{
MakeLocate $(1) : $(LOCATE_SOURCE) ;
Clean clean : $(1) ;
}
actions CreateHeader
{
echo "int x = 10;" > $(1)
}
Object a.o : a.c ;
Object b.o : b.c ;
Object c.o : c.c ;
CreateHeader a.h ;
CreateHeader b.h ;
CreateHeader c.h ;
Here're the details:
SubDir should always be invoked in a Jamfile. It sets up several helpful (and in some cases necessary) variables, including SUBDIR, SEARCH_SOURCE, and LOCATE_SOURCE which are used here.
Adding the "src" subdirectory to SEARCH_SOURCE allows you to omit the "src/" part for the source files in the Object rule invocations. SEARCH_SOURCE is also automatically added to the include directories, which is why the #include directories can be shortened.
LOCATE_SOURCE is the directory where generated source files (e.g. generated yacc sources and headers) are placed. For sake of consistency CreateHeader uses this variable. Note that this allows (and requires) you to omit the "src/" part in the CreateHeader invocations.
So the general thrust of these changes is to omit the "src/" part from target names used in the Jamfile. It is generally recommended to omit directory components in Jamfiles (and use grist for disambiguation instead). It is important to note that the way Jam works targets with the names "src/a.h" and "a.h" are different targets, even if the former is considered to be located in "." and the latter in "./src" (e.g. by means of the on-target SEARCH or LOCATE variables). With the files you gave Jam's header scanning results in the following include dependencies (those are target names):
src/a.c : src/a.h
b.c : src/b.h
src/c.c : c.h
This makes obvious why jamming "c.o" fails: The target "c.h" is unknown, since the target name of the header you declare to be generated is "src/c.h". Hence jam ignores the include dependency. The reason for the failing "jam a.o" is the one you suspected.
The change I suggest requires adjusting the #include directives in the source files, which may not be desirable/possible in your actual use case. The situation would still be salvageable. E.g. you can change the Jamfile as suggested, but extend the CreateHeader rule:
rule CreateHeader
{
MakeLocate $(1) : $(LOCATE_SOURCE) ;
Clean clean : $(1) ;
Depends src/$(1) : $(1) ;
NotFile src/$(1) ;
}
This is obviously a bit of a hack. It defines the targets "src/a.h" and friends as pseudo targets, each depending on the corresponding actual target ("a.h" etc.). This way Jam's header scanning will result in a known target regardless of whether it has the "src/" prefix or not.
The less hacky solution is to explicitly declare the include relations, though:
Includes a.c : a.h ;
Includes b.c : b.h ;

Resources