Skip to content

Commit 41dd126

Browse files
committed
build: add gen-imports to create libc.imports
This adds a python script to generate libc.imports as the shell utilities may not be available on Windows.
1 parent c71578c commit 41dd126

3 files changed

Lines changed: 76 additions & 3 deletions

File tree

.azure-pipelines.yml

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,7 @@ jobs:
4848
rustup update stable --no-self-update
4949
rustup default stable
5050
rustup component add llvm-tools-preview
51-
echo "##vso[task.setvariable variable=WASM_NM;]$(rustc --print sysroot|sed 's|C:|/c|'|sed 's|\\|/|g')/lib/rustlib/x86_64-pc-windows-msvc/bin/llvm-nm.exe"
52-
displayName: Install llvm-nm (Windows)
51+
displayName: Install LLVM tools (Windows)
5352
condition: and(succeeded(), eq( variables['Agent.OS'], 'Windows_NT' ))
5453
- bash: |
5554
echo "##vso[task.setvariable variable=LLVM_AR]$(which llvm-ar)"
@@ -59,10 +58,18 @@ jobs:
5958
echo ##vso[task.setvariable variable=LLVM_AR]%CD%\citools\clang-rust\bin\llvm-ar.exe
6059
displayName: Find llvm-ar (Windows)
6160
condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT'))
61+
- bash: |
62+
echo "##vso[task.setvariable variable=LLVM_NM]$(which llvm-nm)"
63+
displayName: Find llvm-nm (!Windows)
64+
condition: and(succeeded(), not(eq(variables['Agent.OS'], 'Windows_NT')))
65+
- bash: |
66+
echo "##vso[task.setvariable variable=LLVM_NM]$(rustc --print sysroot)\\lib\\rustlib\\x86_64-pc-windows-msvc\\bin\\llvm-nm.exe"
67+
displayName: Find llvm-nm (Windows)
68+
condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT'))
6269
- task: CMake@1
6370
inputs:
6471
workingDirectory: $(Build.BinariesDirectory)
65-
cmakeArgs: -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_SYSTEM_NAME=Generic -DCMAKE_AR=$(LLVM_AR) -DCMAKE_C_COMPILER=clang -S $(Build.SourcesDirectory)
72+
cmakeArgs: -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_SYSTEM_NAME=Generic -DCMAKE_AR=$(LLVM_AR) -DCMAKE_NM=$(LLVM_NM) -DCMAKE_C_COMPILER=clang -S $(Build.SourcesDirectory)
6673
displayName: Configure
6774
- task: CMake@1
6875
inputs:

CMakeLists.txt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ include(CMakeDependentOption)
1111

1212
option(ENABLE_THREADS "enable threads" OFF)
1313

14+
find_package(Python COMPONENTS Interpreter REQUIRED)
15+
1416
add_compile_options(--sysroot=${CMAKE_BINARY_DIR}/sysroot)
1517

1618
# WebAssembly floating point match doesn't trap
@@ -1133,3 +1135,16 @@ foreach(stub m rt pthread crypt util xnet resolve dl)
11331135
add_custom_target(${stub} ALL
11341136
DEPENDS ${CMAKE_BINARY_DIR}/sysroot/lib/lib${stub}.a)
11351137
endforeach()
1138+
1139+
add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/sysroot/lib/libc.imports
1140+
COMMAND
1141+
${Python_EXECUTABLE} ${PROJECT_SOURCE_DIR}/tools/gen-imports.py
1142+
--nm ${CMAKE_NM}
1143+
--output ${CMAKE_BINARY_DIR}/sysroot/lib/libc.imports
1144+
$<TARGET_FILE:c>
1145+
${CMAKE_BINARY_DIR}/sysroot/lib/crt1.o
1146+
DEPENDS
1147+
${PROJECT_SOURCE_DIR}/tools/gen-imports.py)
1148+
add_custom_target(libc.imports ALL
1149+
DEPENDS ${CMAKE_BINARY_DIR}/sysroot/lib/libc.imports)
1150+
add_dependencies(libc.imports c crt1.o)

tools/gen-imports.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#!/usr/bin/env python
2+
# -*- encoding: utf-8 -*-
3+
"""Generate import file for a target
4+
5+
This utility scans a static library to identify the undefined symbols which are
6+
externally visible which it expects to have provided. This is used to generate
7+
the import file definitions for WASI.
8+
9+
Example:
10+
$ python gen-imports.py --nm llvm-nm --prefix __wasi_ libc.a
11+
"""
12+
13+
import argparse
14+
import os
15+
import re
16+
import subprocess
17+
import sys
18+
19+
from subprocess import Popen
20+
21+
def main(argv):
22+
parser = argparse.ArgumentParser('gen-imports')
23+
parser.add_argument('--nm', default = 'nm')
24+
parser.add_argument('--prefix', default = '_?_wasi_')
25+
parser.add_argument('--output', required = True)
26+
27+
args, unparsed = parser.parse_known_args()
28+
29+
args.nm = os.path.normpath(args.nm)
30+
args.output = os.path.normpath(args.output)
31+
32+
process = Popen([
33+
args.nm,
34+
'--undefined-only',
35+
'--extern-only',
36+
'--just-symbol-name',
37+
] + unparsed,
38+
stdout = subprocess.PIPE)
39+
output, error = process.communicate()
40+
41+
prefix = re.compile(args.prefix)
42+
lines = output.decode('utf-8').splitlines()
43+
symbols = [ line for line in lines if not line.endswith(':') ]
44+
45+
with open(args.output, 'w') as imports:
46+
for symbol in sorted(set(symbols)):
47+
if prefix.match(symbol):
48+
imports.write('{}\n'.format(symbols))
49+
50+
if __name__ == '__main__':
51+
main(sys.argv)

0 commit comments

Comments
 (0)