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
我想在这里改进几件事:
- 我想考虑 makefile 中的 swig 文件 (*.i)。例如,每次更改某个 swig 文件时,都应生成一个新的 wrap 文件(即:swig -python -c++ file_has_changed.cpp),然后重建项目
- 我想避免使用硬编码的目标文件。例如,我想以某种方式使用所有使用通配符的 cpp 文件
我已经阅读了一些关于 Makefiles 的文档,但我仍然很困惑。我怎样才能做到这一点?
现在我正在使用 hacky 解决方案,例如 swig -python -c++ whatever_file.i && nmake
,那当然一点也不理想
参考资料
在 visual studio IDE 中实现这个很容易遵循 these steps 但我想在 SublimeText 中使用这个 makefile,这就是为什么我很想知道如何有一个合适的 Makefile
我已经使用 CMake 解决了这个问题,这直接转化为使用 autoconf
和 automake
,从而生成文件。
思路是引入如下变量
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)
给定以下 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
我想在这里改进几件事:
- 我想考虑 makefile 中的 swig 文件 (*.i)。例如,每次更改某个 swig 文件时,都应生成一个新的 wrap 文件(即:swig -python -c++ file_has_changed.cpp),然后重建项目
- 我想避免使用硬编码的目标文件。例如,我想以某种方式使用所有使用通配符的 cpp 文件
我已经阅读了一些关于 Makefiles 的文档,但我仍然很困惑。我怎样才能做到这一点?
现在我正在使用 hacky 解决方案,例如 swig -python -c++ whatever_file.i && nmake
,那当然一点也不理想
参考资料
在 visual studio IDE 中实现这个很容易遵循 these steps 但我想在 SublimeText 中使用这个 makefile,这就是为什么我很想知道如何有一个合适的 Makefile
我已经使用 CMake 解决了这个问题,这直接转化为使用 autoconf
和 automake
,从而生成文件。
思路是引入如下变量
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)