当前位置: 代码迷 >> python >> 使用 Xcode 10 编译 Cython
  详细解决方案

使用 Xcode 10 编译 Cython

热度:88   发布时间:2023-07-14 09:49:44.0

我试图用 Cython 编译一个简单的例子并得到这个链接器错误(macOS,Xcode 10):

gcc -fno-strict-aliasing -I/anaconda2/envs/python2.7-base/include -arch x86_64 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -I/anaconda2/envs/python2.7-base/include/python2.7 -c noway.cpp -o build/temp.macosx-10.6-x86_64-2.7/noway.o -std=c++11 -Os -stdlib=libc++ -mmacosx-version-min=10.7
g++ -bundle -undefined dynamic_lookup -L/anaconda2/envs/python2.7-base/lib -arch x86_64 -arch x86_64 build/temp.macosx-10.6-x86_64-2.7/one.o build/temp.macosx-10.6-x86_64-2.7/noway.o -L/anaconda2/envs/python2.7-base/lib -o /Users/dkotsur/Projects/InCeM/IF-MedialAxis/test/noway.so
clang: warning: libstdc++ is deprecated; move to libc++ with a minimum deployment target of OS X 10.9 [-Wdeprecated]
ld: library not found for -lstdc++
clang: error: linker command failed with exit code 1 (use -v to see invocation)
error: command 'g++' failed with exit status 1

我的anaconda环境是这样的:

Python 2.7.15 |Anaconda custom (64-bit)| (default, May  1 2018, 18:37:05) 
[GCC 4.2.1 Compatible Clang 4.0.1 (tags/RELEASE_401/final)] on darwin

对于 Mac,anaconda 似乎使用 libstdc++ 而不是 libc++。 但我不知道如何解决它。

有没有人有类似的东西? 有关如何处理的任何线索?

这是我的代码 setup.py

if platform.system() == "Windows":
    extra_args = ["/std:c++latest", "/EHsc"]
elif platform.system() == "Darwin":
    extra_args = ['-std=c++11', "-Os", "-stdlib=libc++", "-mmacosx-version-min=10.7"]
else:
    extra_args = []

compile_files = [
    "one.pyx",
    "noway.cpp",
]

include_paths = [
]

ext_modules = [Extension("noway", compile_files,
                         language='c++',
                         include_dirs=include_paths,
                         extra_compile_args=extra_args)]

setup(cmdclass={'build_ext': build_ext}, ext_modules=cythonize(ext_modules))

一个.pyx:

import cython

cdef extern from "noway.hpp":
    cdef void noway();


def nway():
    noway()

noway.hpp

#ifndef noway_h
#define noway_h

void noway();

#endif

noway.cpp

#include "noway.hpp"
#include <iostream>

void noway() {
    std::cout << "No way!!!" << std::endl;
}

谢谢,@ead 发表评论。 你帮了很多忙。

我通过将-stdlib=stdc++添加到额外的链接参数而不是编译参数来修复 setup.py。 我还必须将-mmacosx-version-min=10.9到额外的链接参数中。

所以, setup.py现在看起来像这样:

import platform
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
from Cython.Build import cythonize

compile_extra_args = []
link_extra_args = []

if platform.system() == "Windows":
    compile_extra_args = ["/std:c++latest", "/EHsc"]
elif platform.system() == "Darwin":
    compile_extra_args = ['-std=c++11', "-mmacosx-version-min=10.9"]
    link_extra_args = ["-stdlib=libc++", "-mmacosx-version-min=10.9"]


compile_files = [
    "one.pyx",
    "noway.cpp",
]

ext_modules = [Extension("noway", compile_files,
                         language='c++',
                         extra_compile_args=compile_extra_args,
                         extra_link_args=link_extra_args)]

setup(cmdclass={'build_ext': build_ext}, ext_modules=cythonize(ext_modules))

我遇到了一个相关的程序,试图更新一个旧的 ionics-2 程序,该程序使用带有大量 python 脚本的各种节点模块。 我最终编写了一个程序,该程序允许我使用 3rd 方节点而无需修补它们来解决此问题。 我在提出解决方案时遇到了这篇文章。

该程序基本上即时修补了 clang++ 参数以替换 -mmacosx-version-min=xxx 参数并将环境日志和参数写入 /tmp/vardump.txt

要使用它,只需使用以下内容构建它:

gcc clang_force.c -o clang_force

然后将其复制到 /usr/local/bin cp clang_force /usr/local/bin 然后更改 CXX 环境变量以使用它。 export CXX=/usr/local/bin/force_clang

就是这样。 然后再次执行'npm install'或你的python脚本,一切都很好。 希望有人觉得它有用。

在此站点上获取代码修复: :

/**************************************************************************
 Force clang to use version 10.9 or greater to allow building legacy code
 (overrides any -mmacosx-version-min params passed in)

 ***************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>


#define WAIT_FOR_COMPLETION
static int exec_prog(char **argv);

int main(int argc, char **argv, char **envp)
{

  FILE *fp;
  int rc = 0;

  fp = fopen("/tmp/vardump.txt","a+");
  if (fp!=NULL) {
        for (char **env = envp; *env != 0; env++)
        {
                char *thisEnv = *env;
                fprintf(fp,"%s\n", thisEnv);
        }
        int counter;
        fprintf(fp,"Program Name Is: %s",argv[0]);
        if(argc==1)
                fprintf(fp,"\nNo Extra Command Line Argument Passed Other Than Program Name");
        if(argc>=2)
        {
                fprintf(fp,"\nNumber Of Arguments Passed: %d",argc);
                fprintf(fp,"\n----Following Are The Command Line Arguments Passed----");
                for(counter=0;counter<argc;counter++) {
                        fprintf(fp,"\nargv[%d]: %s",counter,argv[counter]);
                        if (strncmp(argv[counter],"-mmacosx-version-min",20)==0) {
                                argv[counter] = "-mmacosx-version-min=10.9";
                                fprintf(fp,"\nForcing argument to %s",argv[counter]);
                        }
                }

        }
        fclose(fp);
        argv[0] = "/usr/bin/clang++";
        rc = exec_prog(argv);
  }
  return rc;
}
static int exec_prog(char **argv)
{
    FILE *fp;
    fp = fopen("/tmp/vardump.txt","a+");
    if (fp!=NULL) {
        fprintf(fp,"\nExecuting %s\n",argv[0]);
        fclose(fp);
    }
    pid_t   my_pid;
    int     status, timeout /* unused ifdef WAIT_FOR_COMPLETION */;

    if (0 == (my_pid = fork())) {
            if (-1 == execve(argv[0], (char **)argv , NULL)) {
                    perror("child process execve failed [%m]");
                    return -1;
            }
    }

#ifdef WAIT_FOR_COMPLETION
    timeout = 1000;
    while (0 == waitpid(my_pid , &status , WNOHANG)) {
            if ( --timeout < 0 ) {
                    perror("timeout");
                    return -1;
            }
            sleep(1);
    }
    fp = fopen("/tmp/vardump.txt","a+");
    if (fp!=NULL) {


        fprintf(fp,"\n %s WEXITSTATUS %d WIFEXITED %d [status %d]\n",
                argv[0], WEXITSTATUS(status), WIFEXITED(status), status);

        if (1 != WIFEXITED(status) || 0 != WEXITSTATUS(status)) {
                perror("failed, halt system");
                return -1;
        }
        fclose(fp);
   }

#endif
    return 0;
}





  相关解决方案