SWIG 文件更改后如何重建项目?

How to rebuild project after SWIG files changed?

给定以下 makefile:

TARGET = _example.pyd
OFILES = example.obj example_wrap.obj
HFILES =

CC = cl
CXX = cl
LINK = link
CPPFLAGS = -DNDEBUG -DUNICODE -DWIN32 -I. -Id:\virtual_envs\py351\include
CFLAGS = -nologo -Zm200 -Zc:wchar_t- -FS -Zc:strictStrings -O2 -MD -W3 -w44456 -w44457 -w44458
CXXFLAGS = -nologo -Zm200 -Zc:wchar_t- -FS -Zc:strictStrings -D_HAS_EXCEPTIONS=0 -O2 -MD -W3 -w34100 -w34189 -w44996 -w44456 -w44457 -w44458 -wd4577
LFLAGS = /LIBPATH:. /NOLOGO /DYNAMICBASE /NXCOMPAT /DLL /MANIFEST /MANIFESTFILE:$(TARGET).manifest /SUBSYSTEM:WINDOWS /INCREMENTAL:NO
LIBS = /LIBPATH:d:\virtual_envs\py351\libs python35.lib
.SUFFIXES: .c .cpp .cc .cxx .C


{.}.cpp{}.obj::
    $(CXX) -c $(CXXFLAGS) $(CPPFLAGS) -Fo @<<
    $<
<<

{.}.cc{}.obj::
    $(CXX) -c $(CXXFLAGS) $(CPPFLAGS) -Fo @<<
    $<
<<

{.}.cxx{}.obj::
    $(CXX) -c $(CXXFLAGS) $(CPPFLAGS) -Fo @<<
    $<
<<

{.}.C{}.obj::
    $(CXX) -c $(CXXFLAGS) $(CPPFLAGS) -Fo @<<
    $<
<<

{.}.c{}.obj::
    $(CC) -c $(CFLAGS) $(CPPFLAGS) -Fo @<<
    $<
<<

all: $(TARGET)

$(OFILES): $(HFILES)

$(TARGET): $(OFILES)
    $(LINK) $(LFLAGS) /OUT:$(TARGET) @<<
      $(OFILES) $(LIBS)
<<
    mt -nologo -manifest $(TARGET).manifest -outputresource:$(TARGET);2

install: $(TARGET)
    @if not exist d:\virtual_envs\py351\Lib\site-packages mkdir d:\virtual_envs\py351\Lib\site-packages
    copy /y $(TARGET) d:\virtual_envs\py351\Lib\site-packages$(TARGET)

clean:
    -del $(TARGET)
    -del *.obj
    -del *.exp
    -del *.lib
    -del $(TARGET).manifest

test:
    python runme.py

我想在这里改进几件事:

我已经阅读了一些关于 Makefiles 的文档,但我仍然很困惑。我怎样才能做到这一点?

现在我正在使用 hacky 解决方案,例如 swig -python -c++ whatever_file.i && nmake,那当然一点也不理想

参考资料

在 visual studio IDE 中实现这个很容易遵循 these steps 但我想在 SublimeText 中使用这个 makefile,这就是为什么我很想知道如何有一个合适的 Makefile

我已经使用 CMake 解决了这个问题,这直接转化为使用 autoconfautomake,从而生成文件。

思路是引入如下变量

DEPENDENCIES = `swig -M -python -c++ -I. example.i | sed 's/\//g'`

并让你的目标依赖于此。以上生成了您的 SWIG 接口文件可能包含的所有 headers 和 .i 文件的依赖项列表。

从任何类型的源生成任何类型的目标,这就是 makefile 的本质:

.i.cpp:
    swig -python -c++ $<

然而,这种优雅将与 nmake (as opposed to GNU make) if the .cpp file is missing because nmake doesn't try to chain inference rules through a missing link.
此外,如果它们存在,它将静默中断并 "build" 从构建链后面的文件(包括生成的可执行文件)的陈旧版本中中断。

此处可能的 kludges 解决方法(当然,除了放弃 nmake)是:

  • 多次调用 nmake,首先,生成所有文件,这些文件是两个 inference rules 之间的中间步骤(如果它们是从生成的,则可能需要多次调用彼此),然后是最终目标

    • 这需要一个外部脚本,它很可能是另一个 makefile。例如。: 将当前的 Makefile 移动到 main_makefile 并创建一个新的 Makefile,主要目标的命令如下:

      python -c "import os,os.path,subprocess;
                 subprocess.check_call(['nmake', '/F', 'main_makefile']
                     +[os.path.splitext(f)[0]+'.cpp'
                       for f in os.listdir('.') if os.path.isfile(f)
                                                   and f.endswith('.i')])"
      nmake /F main_makefile
      
  • 不仅仅依赖于推理规则,而是对要生成的每个 .cpp 都有一个明确的规则(顺便说一句,CMake 就是这样做的)

    • 这要求自动生成 Makefile 的相关部分。该部分可以是 !INCLUDE',但是在 nmake 开始处理结果之前仍然需要外部代码来生成。示例代码(同样,在 Python 中):

      import os,os.path,subprocess
      for f in os.listdir('.') if os.path.isfile(f) and f.endswith('.i'):
          print '"%s": "%s"'%(os.path.splitext(f)[0]+'.cxx',f)
          #quotes are to allow for special characters,
          # see https://msdn.microsoft.com/en-us/library/956d3677.aspx
          #command is not needed, it will be added from the inferred rule I gave
          # in the beginning, see http://www.darkblue.ch/programming/Namke.pdf, p.41 (567)