I am trying to generate the interface files for a large C++ project using Swig. The header files for the project do some checking based on the compiler type, for instance,
#if defined(__clang__)
...
#if defined(__llvm__)
So I have to pass the compiler flags to Swig. Specifically, it seems to me that I should call swig like this:
swig -D__clang__ ...
However, this does not seem to alleviate the error messages I am getting, since I still get the same errors.
It is not clear to me if I am setting the compiler flags incorrectly, or whether I am not setting all of the compiler flags. So the question is twofold:
Am I setting the compiler flag correctly by calling
swig -D__clang__ ...... xxx.i
or should I somehow define these parameters in the xxx.i interface file?
Richard is correct. Most compilers seem to support the -dM
command (at least clang
and gcc
seem to). In my case, I wanted to see which preprocessor macros were set by the Android build system. This is a little bit complicated since the Android NDK has many compilers, all built slightly differently. Therefore, I created the following python 3 script to save all of the macro includes to file:
import os, sys
# Define the toolchain root
root = "C:\\Android\\android-sdk\\ndk-bundle\\toolchains\\"
# Define the directory where you want all of the macro definitions to go
output = "output\\"
os.makedirs(output, exist_ok=True)
# Get a list of all of the files
files = [ ( os.path.join(dp, f), f ) for dp, dn, fn in os.walk(os.path.expanduser(root)) for f in fn ]
# We only want executables
files = [ file for file in files if file[1].endswith("exe") ]
# Now, let's limit that to executables that contain one of the following keys
keys = [ "gcc", "g++", "clang", "c++", "cpp" ]
files = [ file for file in files if any(key in file[1] for key in keys) ]
# and that exclude the following keys
keys = [ "-ar", "-nm", "-ranlib", "filt", "-format", "-tidy" ]
files = [ file for file in files if all(key not in file[1] for key in keys) ]
# Now, for each of these files, we want to see what preprocessor macros are being set.
call = " -dM -E - < NUL > "
for file in files:
command = file[0] + call + output + file[1].replace(".exe", ".txt" ).replace(root,"")
print(command)
os.system( command )
If you call this file "introspect.py", then usage is simply
python introspect.py
What this script does is to look for all of the *.exe
files (change this for linux systems) in the root
directory (on my system C:\\\\Android\\\\android-sdk\\\\ndk-bundle\\\\toolchains\\\\
) which should contain the compiler somewhere. Specifically, this script will look for all executables with one of the terms
[ "gcc", "g++", "clang", "c++", "cpp" ]
in the name, excluding files with
[ "-ar", "-nm", "-ranlib", "filt", "-format", "-tidy" ]
in the name. Finally, each of the found executables is then run in the format
compiler.exe -dM -E - < NUL > output\compiler.txt
where compiler
will be something like clang
or gcc
or g++
. Note that this script forces the creation of the output
directory. After running on my system, the output
directory contains the files (warning: there really are a lot of compilers available through the NDK):
aarch64-linux-android-c++.txt
aarch64-linux-android-cpp.txt
aarch64-linux-android-g++.txt
aarch64-linux-android-gcc-4.9.txt
aarch64-linux-android-gcc-4.9.x.txt
aarch64-linux-android-gcc.txt
arm-linux-androideabi-c++.txt
arm-linux-androideabi-cpp.txt
arm-linux-androideabi-g++.txt
arm-linux-androideabi-gcc-4.9.txt
arm-linux-androideabi-gcc-4.9.x.txt
arm-linux-androideabi-gcc.txt
clang++.txt
clang.txt
clang_32.txt
i686-linux-android-c++.txt
i686-linux-android-cpp.txt
i686-linux-android-g++.txt
i686-linux-android-gcc-4.9.txt
i686-linux-android-gcc-4.9.x.txt
i686-linux-android-gcc.txt
mips64el-linux-android-c++.txt
mips64el-linux-android-cpp.txt
mips64el-linux-android-g++.txt
mips64el-linux-android-gcc-4.9.txt
mips64el-linux-android-gcc-4.9.x.txt
mips64el-linux-android-gcc.txt
mipsel-linux-android-c++.txt
mipsel-linux-android-cpp.txt
mipsel-linux-android-g++.txt
mipsel-linux-android-gcc-4.9.txt
mipsel-linux-android-gcc-4.9.x.txt
mipsel-linux-android-gcc.txt
x86_64-linux-android-c++.txt
x86_64-linux-android-cpp.txt
x86_64-linux-android-g++.txt
x86_64-linux-android-gcc-4.9.txt
x86_64-linux-android-gcc-4.9.x.txt
x86_64-linux-android-gcc.txt
where the first few lines of those files tend to look like
#define __DBL_MIN_EXP__ (-1021)
#define __UINT_LEAST16_MAX__ 65535
#define __ATOMIC_ACQUIRE 2
#define __FLT_MIN__ 1.17549435082228750796873653722224568e-38F
#define __GCC_IEC_559_COMPLEX 2
#define __UINT_LEAST8_TYPE__ unsigned char
#define __INTMAX_C(c) c ## L
#define __CHAR_BIT__ 8
#define __UINT8_MAX__ 255
#define __ANDROID__ 1
#define __WINT_MAX__ 4294967295U
#define __ORDER_LITTLE_ENDIAN__ 1234
#define __SIZE_MAX__ 18446744073709551615UL
#define __WCHAR_MAX__ 4294967295U
#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1
#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 1
#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 1
It turns out that many of these files are identical, but there are significant differences between the clang
and gcc
files.
You should have a .i file that defines the interface that you want to generate.
There you can simply use #define __clang__
.
For instance, take a look at a swig.i file for a library of mine https://bitbucket.org/binarno/imebra/src/db648a8b9c359524d40fd7d63c785b6269147010/wrappers/swig.i?at=default
Also note that swig does not need all the compiler flags: it is not going to compile your project but it will just generate the additional cxx files. In the .i file just declare the flag (if needed) that allows swig to select the correct classes and method.
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.