简体   繁体   中英

How to rebuild project after SWIG files changed?

Given the below 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

I'd like to improve a couple of things here:

  • I'd like to consider swig files (*.i) in the makefile. For example, every time some swig file has been changed a new wrap file should be generated (ie: swig -python -c++ file_has_changed.cpp) and then rebuild the project
  • I'd like to avoid having hardcoded object files. For instance, I'd like to use all cpp files using wildcards somehow

I've read a little bit of the docs talking about Makefiles but I'm still pretty much confused. How could I achieve this?

Right now I'm using a hacky solution like swig -python -c++ whatever_file.i && nmake , that's of course it's not ideal at all

REFERENCES

Achieving this inside visual studio IDE is quite easy following these steps but I'd like to use this makefile inside SublimeText, that's why I'm quite interested on knowing how to have a proper Makefile

Producing any kind of target from any kind of source, that's the essence of a makefile:

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

This elegance will, however, break with 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 .
Moreover, it will break silently and "build" from stale versions of the files that are later in the build chain (which includes the resulting executable) if they are present.

Possible kludges workarounds here (save for ditching nmake , of course) are:

  • invoke nmake multiple times, first, to generate all files that are an intermediate steps between two inference rules (which can in turn require multiple invocations if they are generated from one another), and then for the final targets

    • This requires an external script which can very well be another makefile. Eg: move the current Makefile to main_makefile and create a new Makefile with commands for the main target like this:

       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 
  • do not rely solely on inference rules but have an explicit rule for each .cpp to be produced (that's what CMake does btw)

    • this asks for the relevant part of Makefile to be autogenerated. That part can be !INCLUDE 'd, but still, external code is needed to do the generation before nmake gets to work on the result. Example code (again, in 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) 

I have solved this using CMake and this translates directly to using autoconf and automake and thereby makefiles.

The idea is to introduce the following variable

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

and make your target depend on this. The above generates a list of dependencies of all headers and .i files your SWIG interface file may include.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM