根据当前操作系统更新makefile中的CFLAGS或LDFLAGS(Update CFLAGS or LDFLAGS in makefile depending on current OS)
我正在尝试创建一个可以在OSX和Linux上运行的makefile。
我的问题是我需要根据操作系统执行makefile来更改
cflags
和ldflags
,但我无法使其工作。 那是我的makefile:OS:=$(shell uname) DST=hello SRC=$(wildcard *.cpp) OBJ=$(SRC:.cpp=.o) CFLAGS= all: clean DetectOS $(DST) DetectOS: ifeq ($(OS),Darwin) @echo OS : $(OS) CC=g++ LDFLAGS="-lm -framework OpenCL" CFLAGS+=-O3 endif ifeq ($(OS),Linux) #Coming soon... endif $(DST): $(OBJ) $(CC) -o $@ $^ $(LDFLAGS) %.o: %.cpp $(CC) -o $@ -c $< $(CFLAGS) clean: rm -rf *.o $(DST)
但是当我运行此代码时,
ifeq
条件块中的cflags
,ldflags
或CC
都不会更新。 我得到以下结果:$ make rm -rf *.o hello OS : Darwin CC=g++ LDFLAGS="-lm -framework OpenCL" CFLAGS+=-O3 cc -o opencl.o -c opencl.cpp cc -o hello opencl.o Undefined symbols for architecture x86_64:....
如您所见,检测到操作系统是因为我们进入了
ifeq
条件块,但CC
未更新并保持未初始化的cc
值。 最后,链接器进程失败,因为ldflags
未引用OpenCL。另一点,如果我不在
LDFLAGS="-lm -framework OpenCL"
输入引号我得到错误:LDFLAGS=-lm -framework OpenCL /bin/sh: -framework: command not found make: *** [DetectOS] Error 127
并且基于多个例子(这里是stackoverflow)我应该没有引号。
我目前在Mac OS X Yosemite上。
I'm trying to create a makefile that will works on both OSX and Linux.
My problem is I need to change
cflags
andldflags
depending on OS the makefile is executed but I can't make it work. That's my makefile :OS:=$(shell uname) DST=hello SRC=$(wildcard *.cpp) OBJ=$(SRC:.cpp=.o) CFLAGS= all: clean DetectOS $(DST) DetectOS: ifeq ($(OS),Darwin) @echo OS : $(OS) CC=g++ LDFLAGS="-lm -framework OpenCL" CFLAGS+=-O3 endif ifeq ($(OS),Linux) #Coming soon... endif $(DST): $(OBJ) $(CC) -o $@ $^ $(LDFLAGS) %.o: %.cpp $(CC) -o $@ -c $< $(CFLAGS) clean: rm -rf *.o $(DST)
But when I run this code, neither
cflags
,ldflags
orCC
are updated in theifeq
conditional block. I get the following result :$ make rm -rf *.o hello OS : Darwin CC=g++ LDFLAGS="-lm -framework OpenCL" CFLAGS+=-O3 cc -o opencl.o -c opencl.cpp cc -o hello opencl.o Undefined symbols for architecture x86_64:....
As you can see, the OS is detected because we went in the
ifeq
conditional block, butCC
isn't updated and keep a non-initialized value ofcc
. Finally the linker process fails because OpenCL is not referenced inldflags
.An other little point, if I don't put quotes in
LDFLAGS="-lm -framework OpenCL"
I get the error :LDFLAGS=-lm -framework OpenCL /bin/sh: -framework: command not found make: *** [DetectOS] Error 127
And based on multiple exemples (here on stackoverflow) I should do it without quotes.
I'm currently on Mac OS X Yosemite.
原文:https://stackoverflow.com/questions/34190747
最满意答案
至于控制流程:
setjmp
返回两次,而longjmp
永远不会返回。 当你第一次调用setjmp
时,为了存储环境,它返回零,当你调用longjmp
,控制流传setjmp
返回参数中提供的值。(注意,
setjmp
实际上不需要是函数;它可能是一个宏。但是,longjmp
是一个函数。)用例通常被称为“错误处理”,“不使用这些功能”。
这是一个小控制流示例:
jmp_buf env; void foo() { longjmp(&env, 10); +---->----+ } | | | | int main() (entry)---+ ^ V { | | | if(setjmp(&env) == 0) | (= 0) | | (= 10) { | ^ | foo(); +---->----+ | } +---->----+ else | { | return 0; +--- (end) } }
笔记:
你不能将0传递给
longjmp
。 如果这样做,则setjmp
返回1
。您不能从相应
longjmp
之前调用setjmp
的函数返回。 换句话说,longjmp
只能在调用堆栈中的setjmp
之上调用。(感谢@wildplasser :)你实际上无法存储
setjmp
的结果。 如果您想以多种不同的方式返回,可以使用switch
:switch (setjmp(&env)) { case 0: // first call case 2: // returned from longjmp(&env, 2) case 5: // returned from longjmp(&env, 5) // etc. }
As for the control flow:
setjmp
returns twice, andlongjmp
never returns. When you callsetjmp
for the first time, to store the environment, it returns zero, and the when you calllongjmp
, the control flow passes to return fromsetjmp
with the value provided in the argument.(Note that
setjmp
needn't actually be functions; it may well be a macro.longjmp
is a function, though.)Use cases are generally cited as "error handling", and "don't use these functions".
Here's a little control flow example:
jmp_buf env; void foo() { longjmp(&env, 10); +---->----+ } | | | | int main() (entry)---+ ^ V { | | | if(setjmp(&env) == 0) | (= 0) | | (= 10) { | ^ | foo(); +---->----+ | } +---->----+ else | { | return 0; +--- (end) } }
Notes:
You cannot pass 0 to
longjmp
. If you do,1
is returned bysetjmp
.You must not return from the function that called
setjmp
before the correspondinglongjmp
. In other words,longjmp
must only be called abovesetjmp
in the call stack.(Thanks to @wildplasser:) You cannot actually store the result of
setjmp
. If you want to return in several different ways, you can use aswitch
, though:switch (setjmp(&env)) { case 0: // first call case 2: // returned from longjmp(&env, 2) case 5: // returned from longjmp(&env, 5) // etc. }
相关问答
更多-
setjmp() / longjmp()完全颠覆堆栈展开,因此也是异常处理以及RAII(一般的析构函数)。 标准中的18.7 / 4“其他运行时支持”: 如果任何自动对象将被抛出的异常将控制权转移到程序中的另一个(目标)点,那么在将控制权转移到同一(目标)点的throw点处对longjmp(jbuf, val)的调用具有未定义的行为。 所以底线是setjmp() / longjmp()在C ++中不能很好地运行。 setjmp()/longjmp() completely subvert stack unw ...
-
错误处理 假设嵌套在许多其他函数中的函数存在错误深度,错误处理只在顶级函数中有意义。 如果两者之间的所有函数都必须正常返回并评估返回值或全局错误变量来确定进一步的处理没有意义甚至是坏的话,这将是非常繁琐和尴尬的。 这就是setjmp / longjmp的意思。 这些情况类似于其他语言(C ++,Java)异常的情况。 协同程序 除了错误处理外,我还可以想到在C中需要setjmp / longjmp的另一种情况: 当你需要实现协同程序时就是这种情况。 这里有一个例子。 我希望它满足Sivaprasad Pal ...
-
setjmp是一个调用_setjmp的宏。 对于x86_64体系结构,它在../sysdeps/x86_64/bsd-_setjmp.S定义。 然后_setjmp将调用__sigsetjmp ,在../sysdeps/x86_64/setjmp.S定义; 此功能严格依赖于平台,需要在汇编中实施。 setjmp is a macro which calls _setjmp. For the x86_64 architecture, it's defined in ../sysdeps/x86_64/bsd-_ ...
-
技术上应该存在,但是这种使用已存在多年并且无法根除(已经尝试过;经常会有一些供应商决定将其作为错误,并在大约一百个左右的错误报告之后恢复)。 小心翼翼地, .h文件应该声明它是extern并且一个 .c / .cpp文件应该定义它。 简而言之,当您没有指定顶级变量的链接( static , extern等)时,它被声明为“常见”。 在链接时,如果对该变量的所有引用都是相同的大小(和类型,如果可用),那么它将被分配一次,并且所有引用都指向它。 如果链接器为同一个变量找到不同的大小/类型/链接,则会引发错误。 ...
-
无跳转编程(Programming without jumps)[2022-08-07]
除非你的跳跃真的是随机的,否则分支预测应该消除大部分涉及的开销。 我将花更多的精力来优化内存访问模式,以改善局部性并减少缓存遗漏。 目前,内存延迟是性能的主要瓶颈。 另一个好的方向是提高并行性(使用向量化的SIMD指令,如果可能的话,使用多个内核)。 Unless your jumps are really random, branch prediction should eliminate most of overhead involved. I would dedicate more effort to ... -
至于控制流程: setjmp返回两次,而longjmp永远不会返回。 当你第一次调用setjmp时,为了存储环境,它返回零,当你调用longjmp ,控制流传setjmp返回参数中提供的值。 (注意, setjmp实际上不需要是函数;它可能是一个宏。但是, longjmp是一个函数。) 用例通常被称为“错误处理”,“不使用这些功能”。 这是一个小控制流示例: jmp_buf env; void foo() { longjmp(&env, 10); +--- ...
-
jmp_buf没有特别好的记录。 在linux标头中,你可以找到类似的东西: typedef int __jmp_buf[6]; struct __jmp_buf_tag { __jmp_buf __jmpbuf; /* Calling environment. */ int __mask_was_saved; /* Saved the signal mask? */ __sigset_t __saved_mask; /* Saved signal mask. */ ...
-
不,你不能使用 int foo = setjmp(buf); foo = setjmp(buf); 稍后(赋值)的原因可能是赋值是一个表达式,它可以在左侧不仅仅包含一个标识符。 如果左侧是左值表达式,则标准不会对子表达式进行评估。 所以,如果你有 int* f(void); *f() = setjmp(buf); *f()和setjmp(buf)可以按任何顺序进行评估。 由于setjmp会对抽象状态机的实际状态进行快照,因此两个命令的语义将完全不同。 对于第一行(初始化),我认为这个问题不会发生。 所以 ...
-
setjmp是可移植的(ISO C89和C99)和ucontext (在SUSv3中过时并从SUSv4 / POSIX 2008中删除)不是。 然而, ucontext在规范方面ucontext 。 实际上,如果你使用setjmp / longjmp以及信号处理程序和备用信号处理堆栈的讨厌黑客,你可以使它们与ucontext一样强大,但它们不是“可移植的”。 也不应该用于多线程。 为此目的POSIX线程(pthread函数)。 我有几个理由说这个: 如果您正在编写线程代码,那么您可能会让它实际并发运行。 我 ...
-
将堆栈内存分配给线程(allocating stack memory to threads)[2023-07-25]
通常,在创建线程时,分配给线程的最大堆栈空间量是固定的,如果线程超过此限制,则结果是未定义的行为 - 没有办法将堆栈空间增加到超出该限制。 如果你很幸运,堆栈溢出将导致某种堆栈溢出异常或信号(取决于操作系统和线程实现),但不能保证。 如果您正在尝试实现自己的线程库,理想情况下您要做的是为每个线程的堆栈分配大量的地址空间,并设置VM系统以根据需要在该空间中分配内存,并在空间已满。 这是大多数操作系统级别的线程库(如pthread或win32线程)所做的,但VM管理的细节很棘手。 如果你不想弄乱VM的东西,你可 ...