Using gmake v3.80, how can I create a rule that ORs together two things. I'm starting with this code:
ifeq "$(BUILD_ARCH)" "lnx86_22"
TEST_ARCH := i86
endif
ifeq "$(BUILD_ARCH)" "linux_24_i86"
TEST_ARCH := i86
endif
And would like to combine the two ifeq(s) into a single if that ORs the two conditions together, perhaps something like this?
ifeq "$(BUILD_ARCH)" "lnx86_22" OR "$(BUILD_ARCH)" "linux_24_i86"
TEST_ARCH := i86
endif
What is the actual syntax that would allow me to do this?
You can use $(filter ...) for that. Like this:
ifneq (,$(filter $(BUILD_ARCH),lnx86_22 linux_24_i86))
TEST_ARCH := i86
endif
Another option would be to use constructed variable names:
lnx86_22_ARCH := i86
linux_24_i86_ARCH := i86
...
TEST_ARCH := $($(BUILD_ARCH)_ARCH)
ifeq (,$(TEST_ARCH))
$(error Failed, unknown arch $(BUILD_ARCH))
Failed, unknown arch $(BUILD_ARCH)
endif
If you are able to upgrade to newer versions of GNU make there are other options available.
Related
I have lines like these in my Makefile, can anyone suggest how to write a loop for it, or any other way to simplify it.
OBJS :=
obj-y :=
include cpu/Makefile
OBJS += $(patsubst %,cpu/%, $(obj-y))
obj-y :=
include drivers/Makefile
OBJS += $(patsubst %,drivers/%, $(obj-y))
obj-y :=
include lib/Makefile
OBJS += $(patsubst %,lib/%, $(obj-y))
obj-y :=
include init/Makefile
OBJS += $(patsubst %,init/%, $(obj-y))
...
Internal Makefiles are without any target and are used for include purpose only. For example cpu/Makefile is something like this:
obj-$(CONFIG_XYZ) += something.c
obj-$(CONFIG_ABC) += something_else.c
All configs are either set to y or n
Let's take this in stages.
First, patsubst is overkill for this job; addprefix will do:
obj-y :=
include cpu/Makefile
OBJS += $(addprefix cpu/, $(obj-y))
Then notice that we can pull "cpu" out as a variable:
DIR=cpu
obj-y :=
include $(DIR)/Makefile
OBJS += $(addprefix $(DIR)/, $(obj-y))
Then use eval and a recipe template or "canned recipe":
define ADD_OBJECTS
obj-y :=
include $(1)/Makefile
OBJS += $$(addprefix $(1)/, $$(obj-y))
endef
$(eval $(call ADD_OBJECTS,cpu))
Then put that eval statement in a foreach loop:
$(foreach DIR,cpu drivers lib init,$(eval $(call ADD_OBJECTS,$(DIR))))
I tried to compile a loadable kernel module, when I stumbled across this weird problem:
obj-m := $(ROOTKIT).o
# $(ROOTKIT)-y += $(CORE_OBJS) $(SRCS_OBJS) $(LIBS_OBJS) $(INCL_OBJS)
$(ROOTKIT)-y += src/core.o src/libs/syscalltable.o src/network_keylog.o src/server.o
$(ROOTKIT)-y += src/module_hiding.o src/getdents_hook.o src/socket_hiding.o src/packet_hiding.o
$(ROOTKIT)-y += src/port_knocking.o src/privilege_escalation.o src/include/utils.o
ccflags-y := -I$(SRCS_H) -I$(LIBS_H) -I$(INCL_H)
This code works fine as is. But when I use the single line $(ROOTKIT)-y which is commented above instead of the three-liner, it only compiles the $(CORE_OBJS) which is only one file. I get the output that all functions defined in the other files are undefined.
Why is that so, even though echo says the content of these variables are the exact same as writing out every filename? Is there a way listing the object files in variables or do i have to manually type all of them every time I add files in the future?
Output of the $(XXXX_OBJS) variables:
src/core.o
src/network_keylog.o src/packet_hiding.o src/module_hiding.o src/getdents_hook.o src/port_knocking.o src/server.o src/socket_hiding.o src/privilege_escalation.o
src/libs/syscalltable.o
src/include/utils.o
EDIT: To have a look at the complete Makefile:
# Module name
ROOTKIT := rootkit
# Build
UNAME := $(shell uname -r)
MODULEDIR := /lib/modules/$(UNAME)
BUILDDIR := $(MODULEDIR)/build
KERNELDIR := $(MODULEDIR)/kernel
# Source files
SRCS_S := src
LIBS_S := src/libs
INCL_S := src/include
# Header files
SRCS_H := $(PWD)/$(SRCS_S)/headers
LIBS_H := $(PWD)/$(LIBS_S)/headers
INCL_H := $(PWD)/$(INCL_S)/headers
# Initial file
CORE := src/core.c
# Objects
CORE := src/core.c
CORE_OBJS := $(patsubst %.c, %.o, $(CORE))
SRCS_OBJS := $(patsubst %.c, %.o, $(filter-out $(CORE), $(wildcard $(SRCS_S)/*.c)))
LIBS_OBJS := $(patsubst %.c, %.o, $(wildcard $(LIBS_S)/*.c))
INCL_OBJS := $(patsubst %.c, %.o, $(wildcard $(INCL_S)/*.c))
# Module
obj-m := $(ROOTKIT).o
# $(ROOTKIT)-y += $(CORE_OBJS) $(SRCS_OBJS) $(LIBS_OBJS) $(INCL_OBJS)
$(ROOTKIT)-y += src/core.o src/libs/syscalltable.o src/network_keylog.o src/server.o
$(ROOTKIT)-y += src/module_hiding.o src/getdents_hook.o src/socket_hiding.o src/packet_hiding.o
$(ROOTKIT)-y += src/port_knocking.o src/privilege_escalation.o src/include/utils.o
ccflags-y := -I$(SRCS_H) -I$(LIBS_H) -I$(INCL_H)
# Recipes
all:
$(MAKE) -C $(BUILDDIR) M=$(PWD) modules
load:
insmod $(KERNELDIR)/net/ipv4/netfilter/nf_reject_ipv4.ko
insmod $(KERNELDIR)/net/ipv6/netfilter/nf_reject_ipv6.ko
insmod rootkit.ko
clean:
$(MAKE) -C $(BUILDDIR) M=$(PWD) clean
You seem to be misusing substitution references.
SRCS := foo.c
OBJS_1 := $(SRCS:.c=.o) # evaluates to 'foo.o'
OBJS_2 := $($(SRCS):.c=.o) # evaluates to nothing
The assignment to OBJS_1 is how substitution refs work; the assignment to OBJS_2 is simply a syntax error, it expands to $(foo.c:.c=.o) and then to '' (since there's no variable with that name). So your assignments like this one:
LIBS_OBJS := $($(wildcard $(LIBS_S)/*.c):.c=.o)
result in empty variables. I don't know how you got the "Output of the $(XXXX_OBJS) variables" (since nothing in your makefile actually displays them), but in fact only CORE_OBJS contains anything, and that's all that gets into $(ROOTKIT)-y.
To fix it, just forgo the substitution references and use patsubst:
LIBS_OBJS := $(patsubst %.c, %.o, $(wildcard $(LIBS_S)/*.c))
EDIT: all right, let's start small and build up.
Step 1: Try the following makefile, and tell us the result (in a comment):
SRCS_S := src
SRCS_OBJS := $(patsubst %.c, %.o, $(wildcard $(SRCS_S)/*.c))
SRC_LIST += $(SRCS_OBJS)
$(info $(SRC_LIST))
(If the output is unmanageable, you might try it with a source directory containing foo.c and bar.c)
I'm considering writing a template to Go code generator and wonder:
If I have many string constants and/or variables with the same value would they be stored in an executable file multiple times or compiler will make an optimisation and store just 1 instance per duplicate and refer it wherever needed?
E.g.
File1.go
========
s1 := "some_string_1"
s2 := "some_string_2"
FileN.go
========
a1 := "some_string_1"
a1 := "some_string_2"
Would it affect file size if I have multiple files with the same constants or compiler is smart enough to make optimization?
Imagine that in many templates I have somthing like:
Template 1
==========
{% for a in list1 %}<td>{{a}}</td>{% endfor %}
Tempalte 2
==========
{% for b in list2 %}<td>{{b.c}}</td><td>{{b.d}}</td>{% endfor %}
that would be translated to something like:
for i, a := range list {
write("<td>")
write(a)
write("</td>")
}
for i, b := range list2 {
write("<td>")
write(b.c)
write("</td></td>")
write(b.d)
write("</td>")
}
Obviously the <td> & </td> would be repeated many times in code. So would it make any sense to create a global array of strings and takes values from it? Something like:
myStrings := [...]string{
"<td>",
"</td>"
}
for i, a := range list {
write(myStrings[0])
write(a)
write(myStrings[1])
}
The language spec says nothing regarding the internal storage of string constants or literals. Based on this discussion I would assume there is currently no interning in the language; https://github.com/golang/go/issues/5160 though that is a bit dated now.
That same search turned up this project which you may find helpful; https://gist.github.com/karlseguin/6570372
From ld's docs:
-X symbol value
Set the value of an otherwise uninitialized string variable. The symbol name should be of the form importpath.name, as displayed in the symbol table printed by "go tool nm".
So this is pretty cool. It allows you to do stuff like this:
package main
import "fmt"
var version string
func main() {
fmt.Println(version)
}
Compile with: go build -ldflags '-X main.version 42' ...
I have two question about his feature. First of all it also works for initialized strings (e.g. var version = "bad build") even though the documentation specifically says "otherwise uninitialized string variable".
The seconds question is about spaces. My Makefile contains the following lines:
GIT_BRANCH := $(shell git rev-parse --abbrev-ref HEAD 2>/dev/null)
GIT_COMMIT := $(shell git rev-parse --short HEAD 2>/dev/null)
LDFLAGS := '-X main.version "$(GIT_BRANCH) $(GIT_COMMIT)"'
The documentation for the go command says:
-ldflags 'flag list'
So they're using single quotes for all linker flags. But what about a string containing spaces as symbol for the -X flag? The double-quotes work just fine, so do escaped single-quotes btw., I'm just not sure I can rely on all that to work consistently given the docs not mentioning any of it.
Clarification of the first question:
Go zero-initializes all vars.
The documentation says: -X symbol value Set the value of an otherwise uninitialized string variable [...].
Does this mean:
var foo string // only this one?
var bar = "bar" // or this one too, maybe
The quotes are handled by the shell (or make), so yes it's consistent.
The calling program populates go's args.
//edit
To use a default version you can use something like this:
var version string
func init() {
if len(version) == 0 {
version = "master"
}
}
//edit 2
From the spec:
When memory is allocated to store a value, either through a
declaration or a call of make or new, and no explicit initialization
is provided, the memory is given a default initialization. Each
element of such a value is set to the zero value for its type: false
for booleans, 0 for integers, 0.0 for floats, "" for strings, and nil
for pointers, functions, interfaces, slices, channels, and maps.
GNU make manual describes usage of computed names as follows:
VAR1 := 5
VARX := VAR1
$(info $((VARX)))
Output: 5
How to use computed name with multiple values inside?
VAR1 := 5
VAR2 := 7
VARY := VAR1 VAR2
$(info ???(VARY))
So that output would be 5 7?
Does NMake have similar functionality?
For GNU-make:
$(foreach item,$(VARY),$($(item)))