首页 \ 问答 \ 根据当前操作系统更新makefile中的CFLAGS或LDFLAGS(Update CFLAGS or LDFLAGS in makefile depending on current OS)

根据当前操作系统更新makefile中的CFLAGS或LDFLAGS(Update CFLAGS or LDFLAGS in makefile depending on current OS)

我正在尝试创建一个可以在OSX和Linux上运行的makefile。

我的问题是我需要根据操作系统执行makefile来更改cflagsldflags ,但我无法使其工作。 那是我的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条件块中的cflagsldflagsCC都不会更新。 我得到以下结果:

$ 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 and ldflags 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 or CC are updated in the ifeq 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, but CC isn't updated and keep a non-initialized value of cc. Finally the linker process fails because OpenCL is not referenced in ldflags.

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
更新时间:2023-12-25 13:12

最满意答案

至于控制流程: 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, and longjmp never returns. When you call setjmp for the first time, to store the environment, it returns zero, and the when you call longjmp, the control flow passes to return from setjmp 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 by setjmp.

  • You must not return from the function that called setjmp before the corresponding longjmp. In other words, longjmp must only be called above setjmp 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 a switch, 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等)时,它被声明为“常见”。 在链接时,如果对该变量的所有引用都是相同的大小(和类型,如果可用),那么它将被分配一次,并且所有引用都指向它。 如果链接器为同一个变量找到不同的大小/类型/链接,则会引发错误。 ...
  • 除非你的跳跃真的是随机的,否则分支预测应该消除大部分涉及的开销。 我将花更多的精力来优化内存访问模式,以改善局部性并减少缓存遗漏。 目前,内存延迟是性能的主要瓶颈。 另一个好的方向是提高并行性(使用向量化的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函数)。 我有几个理由说这个: 如果您正在编写线程代码,那么您可能会让它实际并发运行。 我 ...
  • 通常,在创建线程时,分配给线程的最大堆栈空间量是固定的,如果线程超过此限制,则结果是未定义的行为 - 没有办法将堆栈空间增加到超出该限制。 如果你很幸运,堆栈溢出将导致某种堆栈溢出异常或信号(取决于操作系统和线程实现),但不能保证。 如果您正在尝试实现自己的线程库,理想情况下您要做的是为每个线程的堆栈分配大量的地址空间,并设置VM系统以根据需要在该空间中分配内存,并在空间已满。 这是大多数操作系统级别的线程库(如pthread或win32线程)所做的,但VM管理的细节很棘手。 如果你不想弄乱VM的东西,你可 ...

相关文章

更多

最新问答

更多
  • 您如何使用git diff文件,并将其应用于同一存储库的副本的本地分支?(How do you take a git diff file, and apply it to a local branch that is a copy of the same repository?)
  • 将长浮点值剪切为2个小数点并复制到字符数组(Cut Long Float Value to 2 decimal points and copy to Character Array)
  • OctoberCMS侧边栏不呈现(OctoberCMS Sidebar not rendering)
  • 页面加载后对象是否有资格进行垃圾回收?(Are objects eligible for garbage collection after the page loads?)
  • codeigniter中的语言不能按预期工作(language in codeigniter doesn' t work as expected)
  • 在计算机拍照在哪里进入
  • 使用cin.get()从c ++中的输入流中丢弃不需要的字符(Using cin.get() to discard unwanted characters from the input stream in c++)
  • No for循环将在for循环中运行。(No for loop will run inside for loop. Testing for primes)
  • 单页应用程序:页面重新加载(Single Page Application: page reload)
  • 在循环中选择具有相似模式的列名称(Selecting Column Name With Similar Pattern in a Loop)
  • System.StackOverflow错误(System.StackOverflow error)
  • KnockoutJS未在嵌套模板上应用beforeRemove和afterAdd(KnockoutJS not applying beforeRemove and afterAdd on nested templates)
  • 散列包括方法和/或嵌套属性(Hash include methods and/or nested attributes)
  • android - 如何避免使用Samsung RFS文件系统延迟/冻结?(android - how to avoid lag/freezes with Samsung RFS filesystem?)
  • TensorFlow:基于索引列表创建新张量(TensorFlow: Create a new tensor based on list of indices)
  • 企业安全培训的各项内容
  • 错误:RPC失败;(error: RPC failed; curl transfer closed with outstanding read data remaining)
  • C#类名中允许哪些字符?(What characters are allowed in C# class name?)
  • NumPy:将int64值存储在np.array中并使用dtype float64并将其转换回整数是否安全?(NumPy: Is it safe to store an int64 value in an np.array with dtype float64 and later convert it back to integer?)
  • 注销后如何隐藏导航portlet?(How to hide navigation portlet after logout?)
  • 将多个行和可变行移动到列(moving multiple and variable rows to columns)
  • 提交表单时忽略基础href,而不使用Javascript(ignore base href when submitting form, without using Javascript)
  • 对setOnInfoWindowClickListener的意图(Intent on setOnInfoWindowClickListener)
  • Angular $资源不会改变方法(Angular $resource doesn't change method)
  • 在Angular 5中不是一个函数(is not a function in Angular 5)
  • 如何配置Composite C1以将.m和桌面作为同一站点提供服务(How to configure Composite C1 to serve .m and desktop as the same site)
  • 不适用:悬停在悬停时:在元素之前[复制](Don't apply :hover when hovering on :before element [duplicate])
  • 常见的python rpc和cli接口(Common python rpc and cli interface)
  • Mysql DB单个字段匹配多个其他字段(Mysql DB single field matching to multiple other fields)
  • 产品页面上的Magento Up出售对齐问题(Magento Up sell alignment issue on the products page)